Skip to content

Commit 9738795

Browse files
committed
feat: added blocked status for users
1 parent 8345ad6 commit 9738795

16 files changed

Lines changed: 179 additions & 3 deletions

File tree

app/channels/application_cable/channel.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ def find_authentication(authorization)
2323
def create_authentication(token_type, token)
2424
case token_type
2525
when 'Session'
26-
Sagittarius::Authentication.new(:session, UserSession.find_by(token: token, active: true))
26+
Sagittarius::Authentication.new(:session, UserSession.joins(:user).find_by(token: token, active: true,
27+
users: { blocked_at: nil }))
2728
else
2829
Sagittarius::Authentication.new(:invalid, nil)
2930
end

app/controllers/application_controller.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ def find_authentication(authorization)
1616
def create_authentication(token_type, token)
1717
case token_type
1818
when 'Session'
19-
Sagittarius::Authentication.new(:session, UserSession.find_by(token: token, active: true))
19+
Sagittarius::Authentication.new(:session, UserSession.joins(:user).find_by(token: token, active: true,
20+
users: { blocked_at: nil }))
2021
else
2122
Sagittarius::Authentication.new(:invalid, nil)
2223
end

app/graphql/mutations/users/update.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Update < BaseMutation
1212
description: 'ID of the user to update.'
1313

1414
argument :admin, Boolean, required: false, description: 'New global admin status for the user.'
15+
argument :blocked, Boolean, required: false, description: 'New blocked status for the user.'
1516
argument :email, String, required: false, description: 'New email for the user.'
1617
argument :firstname, String, required: false, description: 'New firstname for the user.'
1718
argument :lastname, String, required: false, description: 'New lastname for the user.'

app/graphql/types/user_type.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ class UserType < Types::BaseObject
1212
null: true,
1313
description: 'Global admin status of the user',
1414
authorize: :read_admin_status
15+
field :blocked, Boolean,
16+
null: true,
17+
description: 'Whether the user is blocked from accessing the application',
18+
authorize: :read_admin_status,
19+
method: :blocked?
1520
field :email, String, null: true, description: 'Email of the user', authorize: :read_email
1621
field :email_verified_at, Types::TimeType,
1722
null: true,

app/models/user.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ def admin?
3939
admin
4040
end
4141

42+
def blocked?
43+
blocked_at.present?
44+
end
45+
4246
def validate_mfa!(mfa)
4347
mfa_passed = false
4448
mfa_type = mfa&.[](:type)

app/services/error_code.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def self.error_codes
3232
mfa_failed: { description: 'Invalid MFA data provided' },
3333
mfa_required: { description: 'MFA is required' },
3434
invalid_login_data: { description: 'Invalid login data provided' },
35+
user_blocked: { description: 'The user is blocked from accessing the application' },
3536
totp_secret_already_set: { description: 'This user already has TOTP set up' },
3637
invalid_totp_secret: { description: 'The TOTP secret is invalid or cannot be verified' },
3738
wrong_totp: { description: 'Invalid TOTP code provided' },
@@ -45,6 +46,8 @@ def self.error_codes
4546
invalid_password_repeat: { description: 'The provided password repeat does not match the password' },
4647
cannot_modify_admin: { description: 'Only administrators can modify admin status of users' },
4748
cannot_modify_own_admin: { description: 'Users cannot modify their own admin status' },
49+
cannot_moderate_user: { description: 'Only administrators can modify moderation status of users' },
50+
cannot_modify_own_blocked_status: { description: 'Users cannot modify their own blocked status' },
4851
user_not_found: { description: 'The user with the given identifier was not found' },
4952
invalid_user_identity: { description: 'The user identity is invalid because of active model errors' },
5053
invalid_user_session: { description: 'The user session is invalid because of active model errors' },

app/services/users/identity/login_service.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ def execute
3636

3737
user = user_identity.user
3838

39+
if user.blocked?
40+
logger.info(message: 'Blocked user tried to login via identity', user_id: user.id, username: user.username,
41+
provider_id: user_identity.provider_id)
42+
return ServiceResponse.error(message: 'User is blocked', error_code: :user_blocked)
43+
end
44+
3945
transactional do |t|
4046
user_session = UserSession.create(user: user)
4147
unless user_session.persisted?

app/services/users/login_service.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ def execute
1919
return ServiceResponse.error(message: 'Invalid login data', error_code: :invalid_login_data)
2020
end
2121

22+
if user.blocked?
23+
logger.info(message: 'Blocked user tried to login', user_id: user.id, username: user.username)
24+
return ServiceResponse.error(message: 'User is blocked', error_code: :user_blocked)
25+
end
26+
2227
transactional do |t|
2328
if mfa.present? && !user.mfa_enabled?
2429
t.rollback_and_return! ServiceResponse.error(message: 'Tried to login via MFA even if mfa is disabled',

app/services/users/update_service.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ def execute
3434
end
3535
end
3636

37+
if params.key?(:blocked)
38+
unless current_authentication.user.admin?
39+
return ServiceResponse.error(message: 'Cannot modify users moderation status because user isn`t admin',
40+
error_code: :cannot_moderate_user)
41+
end
42+
43+
if current_authentication.user == user
44+
return ServiceResponse.error(message: 'Cannot modify own blocked status',
45+
error_code: :cannot_modify_own_blocked_status)
46+
end
47+
end
48+
3749
transactional do |t|
3850
mfa_type = nil
3951
if params.keys.intersect?(REQUIRES_MFA_FIELDS) && user.mfa_enabled? # is "critical" field
@@ -52,7 +64,10 @@ def execute
5264
end
5365
end
5466

55-
success = user.update(params)
67+
update_params = params.except(:blocked)
68+
update_params[:blocked_at] = params[:blocked] ? Time.zone.now : nil if params.key?(:blocked)
69+
70+
success = user.update(update_params)
5671
unless success
5772
t.rollback_and_return! ServiceResponse.error(
5873
message: 'Failed to update user',

spec/factories/users.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
admin { true }
1919
end
2020

21+
trait :blocked do
22+
blocked_at { Time.zone.now }
23+
end
24+
2125
trait :with_namespace do
2226
after :build, &:ensure_namespace
2327
end

0 commit comments

Comments
 (0)