Initial commit

This commit is contained in:
Serghei Mihai 2014-06-04 10:48:36 +02:00
commit 5ffef911fe
13 changed files with 211 additions and 0 deletions

4
Gemfile Normal file
View File

@ -0,0 +1,4 @@
source 'http://rubygems.org'
gem 'oauth2'
gem 'json'

22
Gemfile.lock Normal file
View File

@ -0,0 +1,22 @@
GEM
remote: http://rubygems.org/
specs:
addressable (2.3.2)
faraday (0.7.6)
addressable (~> 2.2)
multipart-post (~> 1.1)
rack (~> 1.1)
json (1.7.5)
multi_json (1.3.6)
multipart-post (1.1.5)
oauth2 (0.5.2)
faraday (~> 0.7)
multi_json (~> 1.0)
rack (1.4.1)
PLATFORMS
ruby
DEPENDENCIES
json
oauth2

View File

@ -0,0 +1,95 @@
require 'account_controller'
require 'json'
require 'oauth2'
class RedmineOauthController < AccountController
include Helpers::MailHelper
include Helpers::Checker
def oauth_a2
if Setting.plugin_redmine_oauth2_a2[:oauth_authentification]
session[:back_url] = params[:back_url]
redirect_to oauth_client.auth_code.authorize_url(:redirect_uri => oauth_a2_callback_url, :scope => 'read')
else
password_authentication
end
end
def oauth_a2_callback
if params[:error]
flash[:error] = l(:notice_access_denied)
redirect_to signin_path
else
token = oauth_client.auth_code.get_token(params[:code], :redirect_uri => oauth_a2_callback_url)
result = token.get(Setting.plugin_redmine_oauth_a2[:a2_server_url] + '/idp/oauth2/user-info/')
info = JSON.parse(result.body)
if info && info["verified_email"]
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_a2_credentials)
redirect_to signin_path
end
end
end
def try_to_login info
params[:back_url] = session[:back_url]
session.delete(:back_url)
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
register_manually_by_administrator(user) do
onthefly_creation_failed(user)
end
end
else
# Existing record
if user.active?
successful_authentication(user)
else
account_pending
end
end
end
def oauth_client
@client ||= OAuth2::Client.new(settings[:client_id], settings[:client_secret],
:site => settings[:a2_server_url],
:authorize_url => '/idp/oauth2/authorize/',
:token_url => '/idp/oauth2/access_token/'
)
end
def settings
@settings ||= Setting.plugin_redmine_oauth2_a2
end
def scopes
Setting.plugin_redmine_oauth2_a2[:a2_scopes_urls]
end
end

View File

@ -0,0 +1,2 @@
module RedmineOauthHelper
end

View File

@ -0,0 +1,7 @@
<% if Setting.plugin_redmine_oauth2_a2[:oauth_authentification] %>
<%= link_to oauth_a2_path(:back_url => back_url) do %>
<%= button_tag :class => 'button-login' do %>
<%= content_tag :div, l(:login_via_oauth2_a2), :class => 'button-login-text' %>
<% end %>
<% end %>
<% end %>

View File

@ -0,0 +1,21 @@
<p>
<label>Client ID:</label>
<%= text_field_tag 'settings[client_id]', @settings[:client_id] %>
</p>
<p>
<label>Client Secret:</label>
<%= text_field_tag 'settings[client_secret]', @settings[:client_secret] %>
</p>
<p>
<label>Server name:</label>
<%= text_field_tag 'settings[a2_server_url]', @settings[:a2_server_url] %>
</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] %>
</p>

5
config/locales/en.yml Normal file
View File

@ -0,0 +1,5 @@
en:
notice_unable_to_obtain_a2_credentials: "Unable to obtain credentials from Authentic."
notice_domain_not_allowed: "You can not login using %{domain} domain."
notice_access_denied: "You must allow to use you Google credentials to enter this site."
login_via_oauth2_a2: "Login via Authentic using OAuth2"

5
config/locales/ru.yml Normal file
View File

@ -0,0 +1,5 @@
ru:
notice_unable_to_obtain_a2_credentials: "Не удалось получить данные от Authentic."
notice_domain_not_allowed: "Вы не можете войти в систему при помощи домена %{domain}."
notice_access_denied: "Для корректного входа необходимо разрешить приложению доступ к аккаунту."
login_via_a2: "Войти с Authentic"

2
config/routes.rb Normal file
View File

@ -0,0 +1,2 @@
get 'oauth_a2', :to => 'redmine_oauth#oauth_a2'
get 'oauth2callback', :to => 'redmine_oauth#oauth_a2_callback', :as => 'oauth_a2_callback'

20
init.rb Normal file
View File

@ -0,0 +1,20 @@
require 'redmine'
require_dependency 'redmine_oauth2_a2/hooks'
Redmine::Plugin.register :redmine_oauth2_a2 do
name 'Redmine Oauth Authentic plugin'
author 'Serghei Mihai'
description 'Plugin for authentication through Authentic'
version '0.0.1'
url ''
author_url ''
settings :default => {
:client_id => "",
:client_secret => "",
:oauth_autentification => false,
:allowed_domains => "",
:a2_server_url => "",
:a2_scopes_urls => "",
}, :partial => 'settings/oauth_settings'
end

11
lib/helpers/checker.rb Normal file
View File

@ -0,0 +1,11 @@
module Helpers
module Checker
def allowed_domain_for? email
allowed_domains = Setting.plugin_redmine_oauth_a2[: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

View File

@ -0,0 +1,8 @@
module Helpers
module MailHelper
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

View File

@ -0,0 +1,9 @@
module RedmineOauth2A2
class Hooks < Redmine::Hook::ViewListener
def view_account_login_bottom(context = {})
context[:controller].send(:render_to_string, {
:partial => "hooks/view_account_login_bottom",
:locals => context})
end
end
end