diff --git a/CHANGELOG.md b/CHANGELOG.md
index 092c191..a409889 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 1.6.0
+
+* Depend on redmine_bots instead of redmine_telegram_common
+* Google auth confirmation on first page
+* Telegram account connection/2fa connection segregation
+* Don't send code to locked users
+
# 1.5.1
* Add redmine_telegram_common dependency to init.rb
diff --git a/README.md b/README.md
index 823ef3a..f0a7842 100644
--- a/README.md
+++ b/README.md
@@ -15,10 +15,15 @@ Supports:
## Requirements
-- [redmine_telegram_common](https://github.com/centosadmin/redmine_telegram_common)
+- [redmine_bots](https://github.com/centosadmin/redmine_bots)
- HTTPS host - Telegram Bot Webhook needs to POST on HTTPS hosts.
- Ruby 2.3+
+### Upgrade to 1.6.0+
+
+From 1.6.0 redmine_2fa depends on [redmine_bots](https://github.com/centosadmin/redmine_bots) instead of redmine_telegram_common.
+Please, install it and follow migration instructions from README of redmine_bots.
+
### Upgrade from 1.3.4 to 1.4.0+
From 1.4.0 redmine_2fa (as well as other Southbridge telegram plugins) is using bot from redmine_telegram_common.
diff --git a/README.ru.md b/README.ru.md
index 9ebf818..5c258a8 100644
--- a/README.ru.md
+++ b/README.ru.md
@@ -17,10 +17,15 @@
## Требования
-- [redmine_telegram_common](https://github.com/centosadmin/redmine_telegram_common)
+- [redmine_bots](https://github.com/centosadmin/redmine_bots)
- HTTPS - нужен для того, чтобы принимать сообщение от Telegram Bot API ([веб-хук](https://tlgrm.ru/docs/bots/api#setwebhook))
- Ruby 2.3+
+### Обновление до 1.6.0 и выше
+
+Начиная с версии 1.6.0 redmine_2fa зависит от [redmine_bots](https://github.com/centosadmin/redmine_bots) вместо redmine_telegram_common.
+Пожалуйста, установите redmine_bots и следуйте инструкциям по миграции данных в его README.
+
### Обновление с 1.3.4 до 1.4.0+
Начиная с версии 1.4.0 redmine_2fa (так же, как и другие telegram-плагины от Southbridge) использует бота из redmine_telegram_common.
diff --git a/app/models/redmine_2fa/telegram_connection.rb b/app/models/redmine_2fa/telegram_connection.rb
new file mode 100644
index 0000000..19dff2f
--- /dev/null
+++ b/app/models/redmine_2fa/telegram_connection.rb
@@ -0,0 +1,5 @@
+module Redmine2FA
+ class TelegramConnection < ActiveRecord::Base
+ belongs_to :user
+ end
+end
diff --git a/app/views/account/init_2fa/_google_auth.html.erb b/app/views/account/init_2fa/_google_auth.html.erb
index 2568661..5a5f922 100644
--- a/app/views/account/init_2fa/_google_auth.html.erb
+++ b/app/views/account/init_2fa/_google_auth.html.erb
@@ -6,8 +6,16 @@
-
-
- <%= submit_tag t('redmine_2fa.second_authentications.next_button_html'), onclick: "$('#init2FAForm').submit();" %>
-
+ <%= form_tag(confirm_otp_path) do %>
+
+ <%= t 'redmine_2fa.auth_code' %>:
+
+
+ <%= text_field_tag :otp_code, nil, autocomplete: 'off', autofocus: true %>
+
+ <%= hidden_field_tag :protocol, 'google_auth' %>
+
+
+
+ <% end %>
diff --git a/app/views/account/init_2fa/_telegram.html.erb b/app/views/account/init_2fa/_telegram.html.erb
index 69c5a53..583270e 100644
--- a/app/views/account/init_2fa/_telegram.html.erb
+++ b/app/views/account/init_2fa/_telegram.html.erb
@@ -1,3 +1,3 @@
- <%= render partial: 'telegram_login/widget' %>
+ <%= render partial: 'telegram_login/widget', locals: { context: '2fa_connection' } %>
diff --git a/app/views/account/otp.html.erb b/app/views/account/otp.html.erb
index ae1f8c1..dd41246 100644
--- a/app/views/account/otp.html.erb
+++ b/app/views/account/otp.html.erb
@@ -15,7 +15,7 @@
- <%= t('redmine_2fa.resend.instruction_html', timeout: 30, bot_name: Setting.plugin_redmine_telegram_common['bot_name']) %>
+ <%= t('redmine_2fa.resend.instruction_html', timeout: 30) %>
diff --git a/app/views/account/telegram_login.html.erb b/app/views/account/telegram_login.html.erb
new file mode 100644
index 0000000..cbc6283
--- /dev/null
+++ b/app/views/account/telegram_login.html.erb
@@ -0,0 +1 @@
+<%= render partial: 'account/init_2fa/telegram' %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index b7facac..360534c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -39,12 +39,13 @@ en:
instruction: Please choose type of two-factor authentication
disable: "Do not use"
next_button_html: Next »
+ next_input_html: Next;
google_auth:
instruction_html: |
Please setup Google Authenticator follow
the instruction .
Use this QR-code in application.
- next_step_instruction: After app setup click "Next".
+ next_step_instruction: After app setup, enter the confirmation code and click "Next".
telegram:
instruction_html: |
%{bot_name} will send you authentication codes. Please activate it.
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index c0ded7e..f6b0be3 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -40,12 +40,13 @@ ru:
instruction: Пожалуйста, выберите способ двухфакторной аутентификации
disable: "Не использовать"
next_button_html: Далее »
+ next_input_html: Далее
google_auth:
instruction_html: |
Установите приложение Google Authenticator следуя инструкции по
ссылке .
Используйте предложенный ниже QR-код в приложении.
- next_step_instruction: После настройки приложения, нажмите "Далее".
+ next_step_instruction: После настройки приложения введите код подтверждения и нажмите "Далее".
telegram:
instruction_html: |
Бот "%{bot_name}" будет отправлять вам коды авторизации.
diff --git a/db/migrate/010_create_telegram_connections.rb b/db/migrate/010_create_telegram_connections.rb
new file mode 100644
index 0000000..46192a3
--- /dev/null
+++ b/db/migrate/010_create_telegram_connections.rb
@@ -0,0 +1,9 @@
+class CreateTelegramConnections < ActiveRecord::Migration
+ def change
+ create_table :redmine_2fa_telegram_connections do |t|
+ t.belongs_to :user, index: true, foreign_key: true
+ t.integer :telegram_id
+ end
+ add_index :redmine_2fa_telegram_connections, :telegram_id
+ end
+end
\ No newline at end of file
diff --git a/db/migrate/011_transfer_telegram_connections.rb b/db/migrate/011_transfer_telegram_connections.rb
new file mode 100644
index 0000000..5bd339a
--- /dev/null
+++ b/db/migrate/011_transfer_telegram_connections.rb
@@ -0,0 +1,8 @@
+class TransferTelegramConnections < ActiveRecord::Migration
+ def up
+ User.where(two_fa_id: Redmine2FA::AuthSource::Telegram.first.id).each do |user|
+ next unless user.telegram_account
+ Redmine2FA::TelegramConnection.create!(user_id: user.id, telegram_id: user.telegram_account.telegram_id)
+ end
+ end
+end
\ No newline at end of file
diff --git a/init.rb b/init.rb
index d5739d5..a2c24cd 100644
--- a/init.rb
+++ b/init.rb
@@ -1,4 +1,4 @@
-require_dependency Rails.root.join('plugins','redmine_telegram_common', 'init')
+require_dependency Rails.root.join('plugins','redmine_bots', 'init')
FileUtils.mkdir_p(Rails.root.join('log/redmine_2fa')) unless Dir.exist?(Rails.root.join('log/redmine_2fa'))
@@ -23,7 +23,7 @@
Redmine::Plugin.register :redmine_2fa do
name 'Redmine 2FA'
- version '1.5.1'
+ version '1.6.0'
url 'https://github.com/centosadmin/redmine_2fa'
description 'Two-factor authorization for Redmine'
author 'Southbridge'
@@ -31,10 +31,9 @@
requires_redmine version_or_higher: '3.0'
- requires_redmine_plugin :redmine_telegram_common, '0.7.0'
+ requires_redmine_plugin :redmine_bots, '0.1.0'
- settings(default: { 'bot_token' => '',
- 'required' => false,
+ settings(default: { 'required' => false,
'active_protocols' => Redmine2FA::AVAILABLE_PROTOCOLS
},
partial: 'settings/redmine_2fa')
diff --git a/lib/redmine_2fa.rb b/lib/redmine_2fa.rb
index 661c840..662a2fc 100644
--- a/lib/redmine_2fa.rb
+++ b/lib/redmine_2fa.rb
@@ -21,18 +21,10 @@ def self.switched_off?
active_protocols.size.zero? || active_protocols.size == 1 && active_protocols.include?('none')
end
- def self.bot_token
- Setting.plugin_redmine_telegram_common['bot_token']
- end
-
def self.logger
Logger.new(Rails.root.join('log', 'redmine_2fa', 'bot-update.log'))
end
- def self.handle_message(message)
- TelegramCommon::Bot.new(bot_token, message).call if message.is_a?(Telegram::Bot::Types::Message)
- end
-
module Configuration
def self.configuration
Redmine::Configuration['redmine_2fa']
diff --git a/lib/redmine_2fa/code_sender/telegram_sender.rb b/lib/redmine_2fa/code_sender/telegram_sender.rb
deleted file mode 100644
index 1cfd65c..0000000
--- a/lib/redmine_2fa/code_sender/telegram_sender.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module Redmine2FA
- class CodeSender::TelegramSender < CodeSender
- attr_reader :errors, :user
-
- def initialize(user)
- @user = user
- @telegram_account = user.telegram_account
- @errors = []
- end
-
- def send_message
- if @telegram_account.present? && @telegram_account.active?
- token = Redmine2FA.bot_token
- bot = Telegram::Bot::Client.new(token)
-
- message = I18n.t('redmine_2fa.telegram_auth.message',
- app_title: Setting.app_title, code: code, expiration_time: timestamp)
-
- bot.api.send_message(chat_id: @telegram_account.telegram_id, text: message)
- end
- rescue Telegram::Bot::Exceptions::ResponseError => e
- errors << "Telegram Bot API: #{e.message}"
- end
- end
-end
diff --git a/lib/redmine_2fa/patches/account_controller_patch/confirm_methods.rb b/lib/redmine_2fa/patches/account_controller_patch/confirm_methods.rb
index 1cb8c6c..7416f35 100644
--- a/lib/redmine_2fa/patches/account_controller_patch/confirm_methods.rb
+++ b/lib/redmine_2fa/patches/account_controller_patch/confirm_methods.rb
@@ -27,6 +27,7 @@ def confirm_2fa
def confirm_otp
if @user.authenticate_otp(params[:otp_code], drift: 120)
+ update_two_fa if @user.two_fa.nil?
reset_otp_session
successful_authentication(@user)
else
diff --git a/lib/redmine_2fa/patches/account_controller_patch/second_authentication_init.rb b/lib/redmine_2fa/patches/account_controller_patch/second_authentication_init.rb
index afdbbfa..ff215f0 100644
--- a/lib/redmine_2fa/patches/account_controller_patch/second_authentication_init.rb
+++ b/lib/redmine_2fa/patches/account_controller_patch/second_authentication_init.rb
@@ -5,7 +5,7 @@ module SecondAuthenticationInit
private
def password_authentication
- if Redmine2FA.switched_off? || @user.ignore_2fa? || @user.two_factor_authenticable?
+ if Redmine2FA.switched_off? || @user.locked? || @user.ignore_2fa? || @user.two_factor_authenticable?
super
else
begin
diff --git a/lib/redmine_2fa/patches/account_controller_patch/second_authentication_step.rb b/lib/redmine_2fa/patches/account_controller_patch/second_authentication_step.rb
index 11077e2..2684ce9 100644
--- a/lib/redmine_2fa/patches/account_controller_patch/second_authentication_step.rb
+++ b/lib/redmine_2fa/patches/account_controller_patch/second_authentication_step.rb
@@ -5,10 +5,10 @@ module SecondAuthenticationStep
private
def password_authentication
- if Redmine2FA.switched_on? && !@user.ignore_2fa? && @user.two_factor_authenticable?
+ if Redmine2FA.switched_on? && !@user.locked? && !@user.ignore_2fa? && @user.two_factor_authenticable?
send_code
flash[:error] = sender.errors.join(', ') if sender.errors.present?
- render(@user.two_fa&.name == 'Telegram' ? 'telegram_login/index' : 'account/otp')
+ render(@user.two_fa&.name == 'Telegram' ? 'account/telegram_login' : 'account/otp')
else
super
end
diff --git a/lib/redmine_2fa/patches/user_patch.rb b/lib/redmine_2fa/patches/user_patch.rb
index 81b0961..067e69b 100644
--- a/lib/redmine_2fa/patches/user_patch.rb
+++ b/lib/redmine_2fa/patches/user_patch.rb
@@ -14,6 +14,7 @@ def self.included(base)
alias_method_chain :update_hashed_password, :otp_auth
belongs_to :two_fa, class_name: 'AuthSource'
+ has_one :telegram_connection, class_name: 'Redmine2FA::TelegramConnection'
end
end
@@ -44,9 +45,12 @@ def google_authenticable?
def reset_second_auth
otp_regenerate_secret
- self.two_fa_id = nil
- self.ignore_2fa = false
- save!
+ self.class.transaction do
+ self.telegram_connection&.destroy!
+ self.two_fa_id = nil
+ self.ignore_2fa = false
+ save!
+ end
end
def confirm_mobile_phone(code)
diff --git a/test/functional/redmine_telegram_connections_controller_test.rb b/test/functional/redmine_telegram_connections_controller_test.rb
deleted file mode 100644
index 0447ce1..0000000
--- a/test/functional/redmine_telegram_connections_controller_test.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require File.expand_path('../../test_helper', __FILE__)
-
-class RedmineTelegramConnectionsControllerTest < ActionController::TestCase
- fixtures :users, :email_addresses, :roles, :auth_sources
-
- setup do
- @user = User.find(2)
- @telegram_account = TelegramCommon::Account.create(telegram_id: 123)
- end
-
- context 'connect with valid data' do
- setup do
- post :create,
- user_id: 2, user_email: @user.mail,
- telegram_id: 123, token: @telegram_account.token,
- plugin: 'plugin_redmine_2fa'
- end
-
- should 'set telegram account to user' do
- @telegram_account.reload
- assert_equal @user, @telegram_account.user
- end
-
- should 'set telegram auth source to user' do
- @user.reload
- assert_equal auth_sources(:telegram), @user.two_fa
- end
- end
-end
diff --git a/test/unit/redmine_2fa/code_sender/telegram_sender_test.rb b/test/unit/redmine_2fa/code_sender/telegram_sender_test.rb
deleted file mode 100644
index 2affb7b..0000000
--- a/test/unit/redmine_2fa/code_sender/telegram_sender_test.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine2FA::CodeSender::TelegramSenderTest < ActiveSupport::TestCase
- fixtures :users, :email_addresses, :roles, :auth_sources
- setup do
- User.any_instance.stubs(:otp_code).returns('123456')
-
- @user = User.find(2)
- @telegram_auth_source = auth_sources(:telegram)
- @user.auth_source = @telegram_auth_source
- end
-
- # context 'initialize with user' do
- #
- # should 'store user' do
- # @sender = Redmine2FA::CodeSender.new(@user)
- # assert_equal @user, @sender.user
- # end
- # should 'store code' do
- # @sender = Redmine2FA::CodeSender.new(@user)
- # assert_equal '123456', @sender.code
- # end
- #
- # should 'store timestamp' do
- # Timecop.freeze(Time.parse('12:00:00 UTC')) do
- # @sender = Redmine2FA::CodeSender.new(@user)
- # assert_equal '12:02:00', @sender.timestamp
- # end
- # end
- #
- #
- # end
-end
diff --git a/test/unit/redmine_2fa/code_sender_test.rb b/test/unit/redmine_2fa/code_sender_test.rb
index 3302af8..0908f8d 100644
--- a/test/unit/redmine_2fa/code_sender_test.rb
+++ b/test/unit/redmine_2fa/code_sender_test.rb
@@ -14,12 +14,6 @@ class Redmine2FA::CodeSenderTest < ActiveSupport::TestCase
end
context 'define sender' do
- should 'be TelegramSender' do
- @user.two_fa = auth_sources(:telegram)
- @sender = Redmine2FA::CodeSender.new(@user)
- assert @sender.sender.is_a?(Redmine2FA::CodeSender::NullSender)
- end
-
should 'be SMSSender' do
@user.two_fa = auth_sources(:sms)
@sender = Redmine2FA::CodeSender.new(@user)
diff --git a/test/unit/telegram_common/bot_test.rb b/test/unit/telegram_common/bot_test.rb
deleted file mode 100644
index e9da1c7..0000000
--- a/test/unit/telegram_common/bot_test.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require File.expand_path('../../../test_helper', __FILE__)
-require 'telegram/bot'
-
-class TelegramCommon::BotTest < ActiveSupport::TestCase
- fixtures :users, :email_addresses, :roles, :auth_sources
-
- setup do
- Redmine2FA.stubs(:bot_token)
- Telegram::Bot::Api.any_instance.stubs(:get_me)
- end
-
- context '/start' do
- setup do
- @telegram_message = ActionController::Parameters.new(
- from: {
- id: 123,
- username: 'dhh',
- first_name: 'David',
- last_name: 'Haselman'
- },
- chat: {
- id: 123,
- type: 'private'
- },
- text: '/start'
- )
-
- @bot_service = TelegramCommon::Bot.new(Redmine2FA.bot_token, @telegram_message)
- end
-
- context 'with user' do
- setup do
- TelegramCommon::Bot.any_instance
- .expects(:send_message)
- .with(I18n.t('telegram_common.bot.start.hello'))
-
- @user = User.find(2)
- @telegram_account = TelegramCommon::Account.create(telegram_id: 123, user_id: @user.id)
-
- @bot_service.call
- end
-
- should 'set telegram auth source' do
- @user.reload
- assert_equal auth_sources(:telegram), @user.two_fa
- end
- end
- end
-end
diff --git a/travis.sh b/travis.sh
index 0664865..df1ce5d 100644
--- a/travis.sh
+++ b/travis.sh
@@ -40,7 +40,7 @@ mv $TESTSPACE/additional_environment.rb config/
# add telegram_common plugin
-git clone git://github.com/centosadmin/redmine_telegram_common.git $PATH_TO_REDMINE/plugins/redmine_telegram_common
+git clone git://github.com/centosadmin/redmine_bots.git $PATH_TO_REDMINE/plugins/redmine_bots
# create a link to the backlogs plugin
ln -sf $PATH_TO_PLUGIN plugins/$NAME_OF_PLUGIN