Skip to content

Commit

Permalink
Merge pull request #110 from kortirso/issue_52
Browse files Browse the repository at this point in the history
IS-52 Attaching more identities to one account
  • Loading branch information
kortirso authored Jun 17, 2023
2 parents ac2f206 + a544274 commit 79b301f
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- login through Gitlab
- expiration time to auth tokens
- removing expired users sessions
- attaching more identities to one account

### Modified
- default insight fields
Expand Down
4 changes: 4 additions & 0 deletions app/assets/stylesheets/general/grid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
margin-top: 1rem;
}

.mr-4 {
margin-right: 1rem;
}

.main-container {
display: flex;
flex-direction: row;
Expand Down
5 changes: 5 additions & 0 deletions app/assets/stylesheets/views/shared/page_navigation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@
}
}
}

.auth-icon {
display: flex;
justify-content: center;
}
10 changes: 10 additions & 0 deletions app/controllers/profiles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
class ProfilesController < ApplicationController
before_action :find_end_time, only: %i[show]
before_action :find_vacations, only: %i[show]
before_action :find_identities, only: %i[show]
before_action :find_not_attached_identities, only: %i[show]

def show; end

Expand Down Expand Up @@ -43,6 +45,14 @@ def find_vacations
.load_async
end

def find_identities
@identities = current_user.identities.order(provider: :asc).load
end

def find_not_attached_identities
@need_identities = Identity.providers.keys - @identities.pluck(:provider)
end

def user_params
params.require(:user).permit(:work_time_zone, :work_start_time, :work_end_time)
end
Expand Down
8 changes: 7 additions & 1 deletion app/controllers/users/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ def validate_auth
end

def user
@user ||= ::Auth::LoginUserService.call(auth: auth).result
@user ||=
if current_user.nil?
::Auth::LoginUserService.call(auth: auth).result
else
::Auth::AttachUserService.new.call(user: current_user, auth: auth)
current_user
end
end

def auth
Expand Down
15 changes: 15 additions & 0 deletions app/services/auth/attach_user_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Auth
class AttachUserService
def call(user:, auth:)
identity = Identity.find_by(uid: auth[:uid], provider: auth[:provider])
return if identity.present?

email = auth[:email]
return if email.nil?

Identities::CreateService.call(user: user, params: auth)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<% else %>
<p id="auth-links">
<span>Login with</span>
<%= link_to image_tag('github.svg', width: 20, height: 20, alt: 'github'), omniauth_link(:github), 'aria-label': 'Login with Github' %>
<%= link_to image_tag('gitlab.svg', width: 20, height: 20, alt: 'gitlab'), omniauth_link(:gitlab), 'aria-label': 'Login with Gitlab' %>
<%= link_to image_tag('github.svg', width: 20, height: 20, alt: 'github'), omniauth_link(:github), 'aria-label': 'Login with Github', class: 'auth-icon' %>
<%= link_to image_tag('gitlab.svg', width: 20, height: 20, alt: 'gitlab'), omniauth_link(:gitlab), 'aria-label': 'Login with Gitlab', class: 'auth-icon' %>
</p>
<% end %>
</div>
Expand Down
27 changes: 26 additions & 1 deletion app/views/controllers/profiles/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
</div>
</div>
<div class="profile-block form-block">
<h2>Work time</h2>
<%= form_with model: Current.user, url: profile_path, method: :patch do |form| %>
<h2>Work time</h2>
<div class="main-container">
<div class="half-container">
<%= form.label :use_work_time, 'Use work time', class: 'form-label' %>
Expand Down Expand Up @@ -63,6 +63,31 @@
<%= form.submit 'Update user data', class: 'button' %>
<% end %>
</div>
<div class="profile-block form-block">
<h2>Identities</h2>
<div class="main-container">
<div class="half-container">
<% @identities.each do |identity| %>
<div class="identity flex justify-between items-center">
<p class="line-height">
<%= identity.provider.capitalize %> identity is created at <%= identity.created_at.strftime('%H:%M %Y-%m-%d') %>
</p>
</div>
<% end %>
<% if @need_identities.present? %>
<p class="line-height mt-4 flex items-center">
<span class="mr-4">Add more identities</span>
<% @need_identities.each do |provider| %>
<%= link_to image_tag("#{provider}.svg", width: 20, height: 20, alt: provider), omniauth_link(provider.to_sym), 'aria-label': "Login with #{provider.capitalize}", class: 'auth-icon mr-4' %>
<% end %>
</p>
<% end %>
</div>
<div class="half-container">
<p class="line-height">Here you can see your connected identities. You can add more or delete existing.</p>
</div>
</div>
</div>
<div class="profile-block form-block">
<h2 class="warning">Delete account</h2>
<p class="line-height">You can delete your account. This is an irreversible action. All your identities, companies, repositories, access tokens and statistics will be destroyed with no chance of recovery.</p>
Expand Down
82 changes: 60 additions & 22 deletions spec/controllers/users/omniauth_callbacks_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,35 +48,73 @@
allow(auth_service).to receive(:result).and_return(auth_payload)
end

context 'for invalid payload' do
let(:auth_payload) do
{
uid: '123',
provider: 'github',
login: 'octocat',
email: nil
}
context 'for not logged user' do
context 'for invalid payload' do
let(:auth_payload) do
{
uid: '123',
provider: 'github',
login: 'octocat',
email: nil
}
end

it 'redirects to root path', :aggregate_failures do
expect { request }.not_to change(User, :count)
expect(response).to redirect_to root_path
end
end

it 'redirects to root path', :aggregate_failures do
expect { request }.not_to change(User, :count)
expect(response).to redirect_to root_path
context 'for valid payload' do
let(:auth_payload) do
{
uid: '123',
provider: 'github',
login: 'octocat',
email: 'email@gmail.com'
}
end

it 'redirects to companies path', :aggregate_failures do
expect { request }.to change(User, :count).by(1)
expect(response).to redirect_to companies_path
end
end
end

context 'for valid payload' do
let(:auth_payload) do
{
uid: '123',
provider: 'github',
login: 'octocat',
email: 'email@gmail.com'
}
context 'for logged user' do
sign_in_user

context 'for invalid payload' do
let(:auth_payload) do
{
uid: '123',
provider: 'github',
login: 'octocat',
email: nil
}
end

it 'redirects to companies path', :aggregate_failures do
expect { request }.not_to change(Identity, :count)
expect(response).to redirect_to companies_path
end
end

it 'redirects to companies path', :aggregate_failures do
expect { request }.to change(User, :count).by(1)
expect(response).to redirect_to companies_path
context 'for valid payload' do
let(:auth_payload) do
{
uid: '123',
provider: 'github',
login: 'octocat',
email: 'email@gmail.com'
}
end

it 'redirects to companies path', :aggregate_failures do
expect { request }.to change(Identity, :count).by(1)
expect(response).to redirect_to companies_path
end
end
end
end
Expand Down
40 changes: 40 additions & 0 deletions spec/services/auth/attach_user_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

describe Auth::AttachUserService, type: :service do
subject(:service_call) { described_class.new.call(user: user, auth: oauth) }

let!(:user) { create :user }
let(:oauth) {
{
uid: '1234567890',
provider: 'github',
login: 'test_first_name',
email: 'test@email.com'
}
}

context 'for unexisting identity' do
it 'creates new Identity' do
expect { service_call }.to change(Identity, :count).by(1)
end

it 'new Identity has params from oauth and belongs to existed user', :aggregate_failures do
service_call

identity = Identity.last

expect(identity.uid).to eq oauth[:uid]
expect(identity.provider).to eq oauth[:provider]
expect(identity.user).to eq user
end
end

context 'for existed identity' do
before { create :identity, uid: oauth[:uid] }

it 'does not create new Identity and returns nil', :aggregate_failures do
expect { service_call }.not_to change(Identity, :count)
expect(service_call).to be_nil
end
end
end

0 comments on commit 79b301f

Please sign in to comment.