From 507dda03d25b5fa8de0e5a1d4c0ca413680ae501 Mon Sep 17 00:00:00 2001
From: Dmitry Kovalenok <dmitry.kovalenok@twinslash.com>
Date: Tue, 13 Nov 2012 20:31:46 +0300
Subject: [PATCH] domain checking implementation

---
 app/controllers/redmine_oauth_controller.rb   |  76 ++++++++++--------
 .../hooks/_view_account_login_bottom.html.erb |   9 ++-
 app/views/settings/_google_settings.html.erb  |   4 +
 assets/images/google_login_icon.jpg           | Bin 2267 -> 3221 bytes
 assets/stylesheets/buttons.css                |  22 +++++
 config/locales/en.yml                         |   4 +-
 config/locales/ru.yml                         |   4 +
 init.rb                                       |   5 +-
 lib/helpers/checker.rb                        |  11 +++
 lib/helpers/mail_helper.rb                    |   6 +-
 .../redmine_oauth_controller_test.rb          |   2 +-
 11 files changed, 103 insertions(+), 40 deletions(-)
 create mode 100644 assets/stylesheets/buttons.css
 create mode 100644 config/locales/ru.yml
 create mode 100644 lib/helpers/checker.rb

diff --git a/app/controllers/redmine_oauth_controller.rb b/app/controllers/redmine_oauth_controller.rb
index 19ba295..68e33d3 100644
--- a/app/controllers/redmine_oauth_controller.rb
+++ b/app/controllers/redmine_oauth_controller.rb
@@ -3,6 +3,7 @@ require 'json'
 
 class RedmineOauthController < AccountController
   include Helpers::MailHelper
+  include Helpers::Checker
   def oauth_google
     if Setting.plugin_redmine_omniauth_google[:oauth_authentification]
       redirect_to oauth_client.auth_code.authorize_url(redirect_uri: oauth_google_callback_url, scope: scopes)
@@ -16,45 +17,54 @@ class RedmineOauthController < AccountController
     result = token.get('https://www.googleapis.com/oauth2/v1/userinfo')
     info = JSON.parse(result.body)
     if info && info["verified_email"]
-      user = User.find_or_initialize_by_mail(info["email"])
-      if user.new_record?
-        # Self-registration off
-        redirect_to(home_url) && return unless Setting.self_registration?
-        # Create on the fly
-        user.firstname, user.lastname = info["name"].split(' ') unless info['name'].nil?
-        user.firstname ||= info[:given_name]
-        user.lastname ||= info[:family_name]
-        user.mail = info["email"]
-        user.login = email_prefix(info["email"])
-        user.login ||= [user.firstname, user.lastname]*"."
-        user.random_password
-        user.register
+      if allowed_domain_for?(info["email"])
+        try_to_login info
+      else
+        flash[:error] = l(:notice_domain_not_allowed, domain: parse_email(info["email"])[:domain])
+        redirect_to signin_path
+      end
+    else
+      flash[:error] = l(:notice_unable_to_obtain_google_credentials)
+      redirect_to signin_path
+    end
+  end
 
-        case Setting.self_registration
-        when '1'
-          register_by_email_activation(user) do
-            onthefly_creation_failed(user)
-          end
-        when '3'
-          register_automatically(user) do
-            onthefly_creation_failed(user)
-          end
-        else
-          register_manually_by_administrator(user) do
-            onthefly_creation_failed(user)
-          end
+  def try_to_login info
+   user = User.find_or_initialize_by_mail(info["email"])
+    if user.new_record?
+      # Self-registration off
+      redirect_to(home_url) && return unless Setting.self_registration?
+      # Create on the fly
+      user.firstname, user.lastname = info["name"].split(' ') unless info['name'].nil?
+      user.firstname ||= info[:given_name]
+      user.lastname ||= info[:family_name]
+      user.mail = info["email"]
+      user.login = parse_email(info["email"])[:login]
+      user.login ||= [user.firstname, user.lastname]*"."
+      user.random_password
+      user.register
+
+      case Setting.self_registration
+      when '1'
+        register_by_email_activation(user) do
+          onthefly_creation_failed(user)
+        end
+      when '3'
+        register_automatically(user) do
+          onthefly_creation_failed(user)
         end
       else
-        # Existing record
-        if user.active?
-          successful_authentication(user)
-        else
-          account_pending
+        register_manually_by_administrator(user) do
+          onthefly_creation_failed(user)
         end
       end
     else
-      flash[:error] = l(:notice_unable_to_obtain_google_credentials)
-      redirect_to signin_path
+      # Existing record
+      if user.active?
+        successful_authentication(user)
+      else
+        account_pending
+      end
     end
   end
 
diff --git a/app/views/hooks/_view_account_login_bottom.html.erb b/app/views/hooks/_view_account_login_bottom.html.erb
index 524d507..969cc24 100644
--- a/app/views/hooks/_view_account_login_bottom.html.erb
+++ b/app/views/hooks/_view_account_login_bottom.html.erb
@@ -1,3 +1,10 @@
+<%= stylesheet_link_tag 'buttons', plugin: 'redmine_omniauth_google' %>
+
 <% if Setting.plugin_redmine_omniauth_google[:oauth_authentification] %>
-  <%= link_to image_tag('/plugin_assets/redmine_omniauth_google/images/google_login_icon.jpg'), oauth_google_path %>
+  <%= link_to oauth_google_path do %>
+    <%= button_tag class: 'button-login' do %>
+      <%= image_tag('/plugin_assets/redmine_omniauth_google/images/google_login_icon.jpg', class: 'button-login-icon', alt: l(:login_via_google)) %>
+      <%= content_tag :div, 'Login_via_google', class: 'button-login-text' %>
+    <% end %>
+  <% end %>
 <% end %>
\ No newline at end of file
diff --git a/app/views/settings/_google_settings.html.erb b/app/views/settings/_google_settings.html.erb
index 969f568..bd32d77 100644
--- a/app/views/settings/_google_settings.html.erb
+++ b/app/views/settings/_google_settings.html.erb
@@ -6,6 +6,10 @@
   <label>Client Secret:</label>
   <%= text_field_tag 'settings[client_secret]', @settings[:client_secret] %>
 </p>
+<p>
+  <label>Available domains</label>
+  <%= text_area_tag "settings[allowed_domains]", @settings[:allowed_domains], rows: 5 %>
+</p>
 <p>
   <label>Oauth authentification:</label>
   <%= check_box_tag "settings[oauth_authentification]", true, @settings[:oauth_authentification] %>
diff --git a/assets/images/google_login_icon.jpg b/assets/images/google_login_icon.jpg
index 1f6cb5393098569ce2ef78b3a6142050118d8fec..f15c939f0040955560d316a90bf48cb81de5eb95 100644
GIT binary patch
literal 3221
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

delta 2261
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

diff --git a/assets/stylesheets/buttons.css b/assets/stylesheets/buttons.css
new file mode 100644
index 0000000..91cbada
--- /dev/null
+++ b/assets/stylesheets/buttons.css
@@ -0,0 +1,22 @@
+.button-login {
+  position: absolute;
+  left: 40%;
+  display: inline-block;
+  border: 1px solid #999;
+  border-radius: 2px;
+  margin-top: 5px;
+  width: 135px;
+  height: 25px;
+  padding: 0;
+}
+
+.button-login-icon {
+  float: left;
+  height: 25px;
+}
+
+.button-login-text {
+  line-height: 21px;
+  background-image: -webkit-linear-gradient(bottom, #ddd, white);
+  font-size: 12px;
+}
\ No newline at end of file
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 186006c..ac32042 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,3 +1,5 @@
 # English strings go here for Rails i18n
 en:
-  notice_unable_to_obtain_google_credentials: "Unable to obtain credentials from Google. You have not yet registered."
\ No newline at end of file
+  notice_unable_to_obtain_google_credentials: "Unable to obtain credentials from Google."
+  notice_domain_not_allowed: "You can not login using %{domain} domain."
+  login_via_google: "Login via Google"
\ No newline at end of file
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
new file mode 100644
index 0000000..5655666
--- /dev/null
+++ b/config/locales/ru.yml
@@ -0,0 +1,4 @@
+ru:
+  notice_unable_to_obtain_google_credentials: "Не удалось получить данные от Google."
+  notice_domain_not_allowed: "Вы не можете войти в систему при помощи домена %{domain}."
+  login_via_google: "Войти с Google"
\ No newline at end of file
diff --git a/init.rb b/init.rb
index d12705b..7274dbd 100644
--- a/init.rb
+++ b/init.rb
@@ -10,5 +10,8 @@ Redmine::Plugin.register :redmine_omniauth_google do
   author_url 'https://tsdv.net/redmine/users/105'
   settings default: {
     client_id: '214698823792.apps.googleusercontent.com',
-    client_secret: 'M0HJPMypEgrDAKKHGiP6Y2R-', oauth_autentification: false}, partial: 'settings/google_settings'
+    client_secret: 'M0HJPMypEgrDAKKHGiP6Y2R-',
+    oauth_autentification: false,
+    allowed_domains: ""
+  }, partial: 'settings/google_settings'
 end
\ No newline at end of file
diff --git a/lib/helpers/checker.rb b/lib/helpers/checker.rb
new file mode 100644
index 0000000..71c494a
--- /dev/null
+++ b/lib/helpers/checker.rb
@@ -0,0 +1,11 @@
+module Helpers
+  module Checker
+    def allowed_domain_for? email
+      allowed_domains = Setting.plugin_redmine_omniauth_google[:allowed_domains]
+      return unless allowed_domains
+      allowed_domains = allowed_domains.split
+      return true if allowed_domains.empty?
+      allowed_domains.index(parse_email(email)[:domain])
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/helpers/mail_helper.rb b/lib/helpers/mail_helper.rb
index d1087f9..5515212 100644
--- a/lib/helpers/mail_helper.rb
+++ b/lib/helpers/mail_helper.rb
@@ -1,8 +1,8 @@
 module Helpers
   module MailHelper
-    def email_prefix email
-      prefix = email.match(/(.+?)@/) if email
-      prefix[1] if prefix
+    def parse_email email
+      email_data = email && email.is_a?(String) ? email.match(/(.*?)@(.*)/) : nil
+      {login: email_data[1], domain: email_data[2]} if email_data
     end
   end
 end
\ No newline at end of file
diff --git a/test/functional/redmine_oauth_controller_test.rb b/test/functional/redmine_oauth_controller_test.rb
index ccb3fa3..757a542 100644
--- a/test/functional/redmine_oauth_controller_test.rb
+++ b/test/functional/redmine_oauth_controller_test.rb
@@ -61,7 +61,7 @@ class RedmineOauthControllerTest < ActionController::TestCase
     assert_redirected_to controller: 'my', action: 'account'
     user = User.find_by_mail(@default_response_body[:email])
     assert_equal user.mail, @default_response_body[:email]
-    assert_equal user.login, email_prefix(@default_response_body[:email])
+    assert_equal user.login, parse_email(@default_response_body[:email])[:login]
   end
 
   def test_oauth_google_callback_for_new_user_with_valid_credentials_and_sefregistration_disabled
-- 
GitLab