-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2297cb6
commit 5d57419
Showing
18 changed files
with
248 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,3 +69,5 @@ gem 'seed-fu', '~> 2.3' | |
gem 'sidekiq', '~> 7.1' | ||
|
||
gem 'lograge', '~> 0.14.0' | ||
|
||
gem 'declarative_policy', '~> 1.1' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# frozen_string_literal: true | ||
|
||
module Mutations | ||
module Users | ||
class Logout < BaseMutation | ||
description 'Logout an existing user session' | ||
|
||
field :user_session, Types::UserSessionType, null: true, description: 'The logged out user session' | ||
|
||
argument :user_session_id, Types::GlobalIdType[::UserSession], required: true, | ||
description: 'ID of the session to logout' | ||
|
||
def resolve(user_session_id:) | ||
user_session = SagittariusSchema.object_from_id(user_session_id) | ||
|
||
return { user_session: nil, errors: ['Invalid user session'] } if user_session.nil? | ||
|
||
UserLogoutService.new(current_user, user_session).execute.to_mutation_response(success_key: :user_session) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
module Ability | ||
module_function | ||
|
||
def allowed?(user, ability, subject = :global) | ||
policy = policy_for(user, subject) | ||
|
||
policy.allowed?(ability) | ||
end | ||
|
||
def policy_for(user, subject = :global) | ||
Cache.policies ||= {} | ||
|
||
DeclarativePolicy.policy_for(user, subject, cache: Cache.policies) | ||
end | ||
|
||
class Cache < ActiveSupport::CurrentAttributes | ||
attribute :policies | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# frozen_string_literal: true | ||
|
||
class BasePolicy < DeclarativePolicy::Base | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# frozen_string_literal: true | ||
|
||
class UserSessionPolicy < BasePolicy | ||
condition(:session_owner) { @subject.user_id == @user&.id } | ||
|
||
rule { session_owner }.enable :logout_session | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# frozen_string_literal: true | ||
|
||
class UserLogoutService | ||
include Sagittarius::Loggable | ||
|
||
def initialize(current_user, user_session) | ||
@current_user = current_user | ||
@user_session = user_session | ||
end | ||
|
||
def execute | ||
unless Ability.allowed?(@current_user, :logout_session, @user_session) | ||
return ServiceResponse.error(payload: "You can't log out this session") | ||
end | ||
|
||
@user_session.active = false | ||
|
||
if @user_session.save | ||
logger.info(message: 'Logged out session', session_id: @user_session.id, user_id: @user_session.user_id) | ||
ServiceResponse.success(message: 'Logged out session', payload: @user_session) | ||
else | ||
logger.warn(message: 'Failed to log out session', session_id: @user_session.id, user_id: @user_session.user_id) | ||
ServiceResponse.error(payload: 'Failed to log out session') | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
id | ||
user | ||
token | ||
active | ||
] | ||
end | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe UserSessionPolicy do | ||
subject { described_class.new(current_user, user_session) } | ||
|
||
let(:current_user) { nil } | ||
let(:user_session) { nil } | ||
|
||
context 'when user is owner of the session' do | ||
let(:current_user) { create(:user) } | ||
let(:user_session) { create(:user_session, user: current_user) } | ||
|
||
it { is_expected.to be_allowed(:logout_session) } | ||
end | ||
|
||
context 'when user is not owner of the session' do | ||
let(:current_user) { create(:user) } | ||
let(:user_session) { create(:user_session) } | ||
|
||
it { is_expected.not_to be_allowed(:logout_session) } | ||
end | ||
|
||
context 'when user is nil' do | ||
let(:current_user) { nil } | ||
let(:user_session) { create(:user_session) } | ||
|
||
it { is_expected.not_to be_allowed(:logout_session) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe 'usersLogout Mutation' do | ||
include GraphqlHelpers | ||
|
||
let(:mutation) do | ||
<<~QUERY | ||
mutation($input: UsersLogoutInput!) { | ||
usersLogout(input: $input) { | ||
errors | ||
userSession { | ||
id | ||
active | ||
} | ||
} | ||
} | ||
QUERY | ||
end | ||
|
||
let(:user_session_id) { nil } | ||
let(:current_user) { nil } | ||
let(:variables) { { input: { userSessionId: user_session_id } } } | ||
|
||
before { post_graphql mutation, variables: variables, current_user: current_user } | ||
|
||
context 'when input is valid' do | ||
let(:user_session) { create(:user_session) } | ||
let(:user_session_id) { user_session.to_global_id.to_s } | ||
|
||
context 'when logging out a session of the same user' do | ||
let(:current_user) { user_session.user } | ||
|
||
it 'logs out the session', :aggregate_failures do | ||
expect(graphql_data_at(:users_logout, :user_session, :id)).to eq(user_session_id) | ||
expect(graphql_data_at(:users_logout, :user_session, :active)).to be(false) | ||
end | ||
end | ||
|
||
context 'when logging out a session of another user' do | ||
let(:current_user) { create(:user) } | ||
|
||
it 'does not log out the session', :aggregate_failures do | ||
expect(graphql_data_at(:users_logout, :errors)).to include("You can't log out this session") | ||
expect(graphql_data_at(:users_logout, :user_session)).to be_nil | ||
end | ||
end | ||
end | ||
|
||
context 'when input is invalid' do | ||
let(:current_user) { create(:user) } | ||
|
||
context 'when session id is invalid' do | ||
let(:user_session_id) { 'some random string' } | ||
|
||
it 'raises validation error' do | ||
expect(graphql_errors).to include( | ||
a_hash_including( | ||
'message' => a_string_including("Could not coerce value \"#{user_session_id}\" to UserSessionID") | ||
) | ||
) | ||
end | ||
end | ||
|
||
context 'when session id is does not exist' do | ||
let(:user_session_id) { 'gid://Sagittarius/UserSession/0' } | ||
|
||
it 'raises validation error' do | ||
expect(graphql_data_at(:users_logout, :errors)).to include('Invalid user session') | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe UserLogoutService do | ||
subject(:service_response) { described_class.new(current_user, user_session).execute } | ||
|
||
context 'when current_user can log out user_session' do | ||
let(:current_user) { create(:user) } | ||
let(:user_session) { create(:user_session, user: current_user) } | ||
|
||
it { is_expected.to be_success } | ||
|
||
it 'changes the session to inactive' do | ||
expect { service_response }.to change { user_session.reload.active }.from(true).to(false) | ||
end | ||
end | ||
|
||
context 'when current_user can not log out user_session' do | ||
let(:current_user) { create(:user) } | ||
let(:user_session) { create(:user_session) } | ||
|
||
it { is_expected.not_to be_success } | ||
|
||
it 'does not change the session to inactive' do | ||
expect { service_response }.not_to change { user_session.reload.active } | ||
end | ||
end | ||
|
||
context 'when current_user is nil' do | ||
let(:current_user) { nil } | ||
let(:user_session) { create(:user_session) } | ||
|
||
it { is_expected.not_to be_success } | ||
|
||
it 'does not change the session to inactive' do | ||
expect { service_response }.not_to change { user_session.reload.active } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters