Skip to content

Commit

Permalink
Merge pull request #29 from sad16/12-oauth
Browse files Browse the repository at this point in the history
oauth
  • Loading branch information
sad16 committed Aug 4, 2021
2 parents 38be6d8 + 4fb1bc1 commit 570f807
Show file tree
Hide file tree
Showing 41 changed files with 1,041 additions and 28 deletions.
5 changes: 5 additions & 0 deletions Gemfile
Expand Up @@ -44,6 +44,9 @@ gem 'aws-sdk-s3', require: false
gem 'validate_url'
gem 'cocoon'
gem 'gon'
gem "omniauth", '~> 1.9.1'
gem 'omniauth-vkontakte'
gem 'omniauth-github'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
Expand All @@ -61,11 +64,13 @@ group :development do
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
gem "letter_opener"
end

group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'capybara-email'
gem 'selenium-webdriver'
gem 'webdrivers', '~> 4.0', require: false

Expand Down
49 changes: 49 additions & 0 deletions Gemfile.lock
Expand Up @@ -75,6 +75,9 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (~> 1.2)
xpath (~> 3.2)
capybara-email (3.0.2)
capybara (>= 2.4, < 4.0)
mail
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
cocoon (1.2.15)
Expand Down Expand Up @@ -103,6 +106,23 @@ GEM
factory_bot_rails (5.0.1)
factory_bot (~> 5.0.0)
railties (>= 4.2.0)
faraday (1.5.1)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
ffi (1.10.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
Expand All @@ -111,6 +131,7 @@ GEM
i18n (>= 0.7)
multi_json
request_store (>= 1.0)
hashie (4.1.0)
i18n (1.6.0)
concurrent-ruby (~> 1.0)
jbuilder (2.8.0)
Expand All @@ -121,6 +142,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jwt (2.2.3)
launchy (2.4.3)
addressable (~> 2.3)
less (2.6.0)
Expand All @@ -130,6 +152,8 @@ GEM
less (~> 2.6.0)
sprockets (> 2, < 4)
tilt
letter_opener (1.7.0)
launchy (~> 2.2)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
Expand All @@ -148,9 +172,28 @@ GEM
minitest (5.11.3)
msgpack (1.2.8)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
nio4r (2.3.1)
nokogiri (1.10.1)
mini_portile2 (~> 2.4.0)
oauth2 (1.4.7)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-github (1.4.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
omniauth-oauth2 (1.7.1)
oauth2 (~> 1.4)
omniauth (>= 1.9, < 3)
omniauth-vkontakte (1.7.0)
omniauth-oauth2 (>= 1.5, <= 1.7.1)
orm_adapter (0.5.0)
pg (1.1.4)
pry (0.12.2)
Expand Down Expand Up @@ -218,6 +261,7 @@ GEM
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
ruby2_keywords (0.0.5)
ruby_dep (1.5.0)
rubyzip (1.2.2)
sass (3.7.3)
Expand Down Expand Up @@ -301,6 +345,7 @@ DEPENDENCIES
bootsnap (>= 1.1.0)
byebug
capybara (>= 2.15)
capybara-email
cocoon
coffee-rails (~> 4.2)
devise
Expand All @@ -309,7 +354,11 @@ DEPENDENCIES
jbuilder (~> 2.5)
jquery-rails
launchy
letter_opener
listen (>= 3.0.5, < 3.2)
omniauth (~> 1.9.1)
omniauth-github
omniauth-vkontakte
pg (>= 0.18, < 2.0)
pry-rails
puma (~> 3.11)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/answers_controller.rb
Expand Up @@ -36,8 +36,8 @@ def destroy
end

def mark_as_best
Answers::MarkAsBestService.new.call(current_user, @answer)
rescue Answers::MarkAsBestService::UserNotAuthorError
Services::Answers::MarkAsBest.new.call(current_user, @answer)
rescue Services::Answers::MarkAsBest::UserNotAuthorError
flash_alert("You can't mark the answer, because you aren't author the question")
end

Expand Down
36 changes: 36 additions & 0 deletions app/controllers/authorizations_controller.rb
@@ -0,0 +1,36 @@
class AuthorizationsController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with: :not_found

def enter_email
@auth = Authorization.find_by!(enter_email_token: params[:enter_email_token])
Services::Authorizations::CheckEnterEmail.new.call(@auth)

rescue Services::Authorizations::CheckEnterEmail::ExpiredError
redirect_to root_path, alert: 'Time to enter email has expired'
end

def update_email
auth = Authorization.find_by!(enter_email_token: params[:enter_email_token])
auth = Services::Authorizations::UpdateEmail.new.call(auth, params[:email])
Services::Authorizations::SendConfirmationMail.new.call(auth)

redirect_to new_user_session_path, notice: 'Сonfirmation mail was sent to the email'
rescue Services::Authorizations::UpdateEmail::ExpiredError
redirect_to root_path, alert: 'Time to enter email has expired'
end

def confirm_email
auth = Authorization.find_by!(confirm_email_token: params[:confirm_email_token])
Services::Authorizations::ConfirmEmail.new.call(auth)

redirect_to new_user_session_path, notice: 'Email confirmed. You can sign in'
rescue Services::Authorizations::ConfirmEmail::ExpiredError
redirect_to root_path, alert: 'Time to confirm email has expired'
end

private

def not_found
head 404
end
end
31 changes: 31 additions & 0 deletions app/controllers/oauth_callbacks_controller.rb
@@ -0,0 +1,31 @@
class OauthCallbacksController < Devise::OmniauthCallbacksController
def github
result = Services::Authorizations::Oauth.new.call(omniauth_data)
redirect_process(result)
end

def vkontakte
result = Services::Authorizations::Oauth.new.call(omniauth_data)
redirect_process(result)
end

private

def redirect_process(oauth)
if oauth[:user]
sign_in_and_redirect oauth[:user], event: :authentication

kind = oauth[:auth].provider.to_s.capitalize
set_flash_message(:notice, :success, kind: kind) if is_navigational_format?
elsif oauth[:auth]
token = oauth[:auth].enter_email_token
redirect_to auth_enter_email_path(enter_email_token: token), notice: 'Enter your email for confirmation'
else
redirect_to root_path, alert: 'Something went wrong'
end
end

def omniauth_data
request.env['omniauth.auth']
end
end
6 changes: 6 additions & 0 deletions app/mailers/authorization_mailer.rb
@@ -0,0 +1,6 @@
class AuthorizationMailer < ApplicationMailer
def confirmation_email(auth)
@auth = auth
mail(to: @auth.email, subject: 'Confirmation Email')
end
end
6 changes: 6 additions & 0 deletions app/models/authorization.rb
@@ -0,0 +1,6 @@
class Authorization < ApplicationRecord
belongs_to :user, optional: true

validates :provider, :uid, presence: true
validates :uid, uniqueness: { scope: [:provider] }
end
3 changes: 2 additions & 1 deletion app/models/user.rb
Expand Up @@ -2,13 +2,14 @@ class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
:recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:github, :vkontakte]

has_many :questions, dependent: :destroy
has_many :answers, dependent: :destroy
has_many :rewards, dependent: :nullify
has_many :votes, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :authorizations, dependent: :destroy

def author_of?(resource)
resource.user_id == id
Expand Down
19 changes: 19 additions & 0 deletions app/services/answers/mark_as_best.rb
@@ -0,0 +1,19 @@
module Services
module Answers
class MarkAsBest < ApplicationService
class Error < StandardError; end
class UserNotAuthorError < Error; end

def call(user, answer)
if user.author_of?(answer.question)
ActiveRecord::Base.transaction do
answer.mark_as_best
answer.assign_reward
end
else
raise UserNotAuthorError
end
end
end
end
end
17 changes: 0 additions & 17 deletions app/services/answers/mark_as_best_service.rb

This file was deleted.

8 changes: 5 additions & 3 deletions app/services/application_service.rb
@@ -1,5 +1,7 @@
class ApplicationService
def call
raise NotImplementedError
module Services
class ApplicationService
def call
raise NotImplementedError
end
end
end
17 changes: 17 additions & 0 deletions app/services/authorizations/check_enter_email.rb
@@ -0,0 +1,17 @@
module Services
module Authorizations
class CheckEnterEmail < ApplicationService
class Error < StandardError; end
class ExpiredError < Error; end

def call(auth)
if auth.enter_email_token_expires_at < Time.current
auth.update!(enter_email_token: nil, enter_email_token_expires_at: nil)
raise ExpiredError
end

true
end
end
end
end
21 changes: 21 additions & 0 deletions app/services/authorizations/confirm_email.rb
@@ -0,0 +1,21 @@
module Services
module Authorizations
class ConfirmEmail < ApplicationService
class Error < StandardError; end
class ExpiredError < Error; end

def call(auth)
if auth.confirm_email_token_expires_at < Time.current
auth.update!(confirm_email_token: nil, confirm_email_token_expires_at: nil)
raise ExpiredError
end

auth.update!(
email_confirmation_at: Time.current,
confirm_email_token: nil,
confirm_email_token_expires_at: nil
)
end
end
end
end

0 comments on commit 570f807

Please sign in to comment.