Skip to content
Snippets Groups Projects
Unverified Commit 6854fb5e authored by Ahmad Farhat's avatar Ahmad Farhat Committed by GitHub
Browse files

Fixed banned and pending users being able to access the app (#4642)

parent 36858fbb
Branches
No related tags found
No related merge requests found
Showing with 75 additions and 9 deletions
...@@ -76,7 +76,7 @@ RSpec/AnyInstance: ...@@ -76,7 +76,7 @@ RSpec/AnyInstance:
Enabled: false Enabled: false
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Max: 15 Max: 16
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 13 Max: 13
......
...@@ -372,7 +372,9 @@ ...@@ -372,7 +372,9 @@
"users": { "users": {
"invalid_invite": "Your invitation token is either invalid or incorrect. Please contact your administrator to receive a new one", "invalid_invite": "Your invitation token is either invalid or incorrect. Please contact your administrator to receive a new one",
"email_exists": "An account under this email already exists. Please try again with another email", "email_exists": "An account under this email already exists. Please try again with another email",
"old_password": "The current password you have entered is incorrect" "old_password": "The current password you have entered is incorrect",
"pending": "Your registration is pending approval",
"banned": "You do not have access to this application. Please contact your administrator if you believe this is a mistake"
}, },
"rooms": { "rooms": {
"room_limit": "Room can not be created due to room limit being reached" "room_limit": "Room can not be created due to room limit being reached"
......
...@@ -23,6 +23,9 @@ module Api ...@@ -23,6 +23,9 @@ module Api
# TODO: Add proper error logging for non-verified token hcaptcha # TODO: Add proper error logging for non-verified token hcaptcha
if user.present? && user.authenticate(session_params[:password]) if user.present? && user.authenticate(session_params[:password])
return render_error errors: Rails.configuration.custom_error_msgs[:pending_user] if user.pending?
return render_error errors: Rails.configuration.custom_error_msgs[:banned_user] if user.banned?
sign_in user sign_in user
render_data data: current_user, serializer: CurrentUserSerializer, status: :ok render_data data: current_user, serializer: CurrentUserSerializer, status: :ok
else else
......
...@@ -11,7 +11,7 @@ import Avatar from '../users/user/Avatar'; ...@@ -11,7 +11,7 @@ import Avatar from '../users/user/Avatar';
export default function NavbarSignedIn({ currentUser }) { export default function NavbarSignedIn({ currentUser }) {
const { t } = useTranslation(); const { t } = useTranslation();
const deleteSession = useDeleteSession(); const deleteSession = useDeleteSession({ showToast: true });
const adminAccess = () => { const adminAccess = () => {
const { permissions } = currentUser; const { permissions } = currentUser;
......
...@@ -27,6 +27,7 @@ export default function AuthProvider({ children }) { ...@@ -27,6 +27,7 @@ export default function AuthProvider({ children }) {
permissions: currentUser?.permissions, permissions: currentUser?.permissions,
role: currentUser?.role, role: currentUser?.role,
verified: currentUser?.verified, verified: currentUser?.verified,
status: currentUser?.status,
stateChanging: false, stateChanging: false,
}; };
......
...@@ -26,8 +26,14 @@ export default function useCreateSession() { ...@@ -26,8 +26,14 @@ export default function useCreateSession() {
navigate('/rooms'); navigate('/rooms');
} }
}, },
onError: () => { onError: (err) => {
if (err.response.data.errors === 'PendingUser') {
toast.error(t('toast.error.users.pending'));
} else if (err.response.data.errors === 'BannedUser') {
toast.error(t('toast.error.users.banned'));
} else {
toast.error(t('toast.error.session.invalid_credentials')); toast.error(t('toast.error.session.invalid_credentials'));
}
}, },
}, },
); );
......
...@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'; ...@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import axios from '../../../helpers/Axios'; import axios from '../../../helpers/Axios';
import { useAuth } from '../../../contexts/auth/AuthProvider'; import { useAuth } from '../../../contexts/auth/AuthProvider';
export default function useDeleteSession() { export default function useDeleteSession({ showToast = true }) {
const { t } = useTranslation(); const { t } = useTranslation();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const navigate = useNavigate(); const navigate = useNavigate();
...@@ -18,7 +18,7 @@ export default function useDeleteSession() { ...@@ -18,7 +18,7 @@ export default function useDeleteSession() {
currentUser.stateChanging = true; currentUser.stateChanging = true;
queryClient.refetchQueries('useSessions'); queryClient.refetchQueries('useSessions');
await navigate('/'); await navigate('/');
toast.success(t('toast.success.session.signed_out')); if (showToast) { toast.success(t('toast.success.session.signed_out')); }
currentUser.stateChanging = false; currentUser.stateChanging = false;
}, },
onError: () => { onError: () => {
......
...@@ -6,12 +6,24 @@ import { toast } from 'react-hot-toast'; ...@@ -6,12 +6,24 @@ import { toast } from 'react-hot-toast';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useAuth } from '../contexts/auth/AuthProvider'; import { useAuth } from '../contexts/auth/AuthProvider';
import VerifyAccount from '../components/users/account_activation/VerifyAccount'; import VerifyAccount from '../components/users/account_activation/VerifyAccount';
import useDeleteSession from '../hooks/mutations/sessions/useDeleteSession';
export default function AuthenticatedOnly() { export default function AuthenticatedOnly() {
const { t } = useTranslation(); const { t } = useTranslation();
const currentUser = useAuth(); const currentUser = useAuth();
const location = useLocation(); const location = useLocation();
const match = useMatch('/rooms/:friendlyId'); const match = useMatch('/rooms/:friendlyId');
const deleteSession = useDeleteSession({ showToast: false });
// User is either pending or banned
if (currentUser.signed_in && currentUser.status !== 'active') {
if (currentUser.status === 'pending') {
toast.error(t('toast.error.users.pending'));
} else {
toast.error(t('toast.error.users.banned'));
}
return deleteSession.mutate();
}
if (currentUser.signed_in && !currentUser?.verified) { if (currentUser.signed_in && !currentUser?.verified) {
return <VerifyAccount currentUser={currentUser} />; return <VerifyAccount currentUser={currentUser} />;
......
# frozen_string_literal: true # frozen_string_literal: true
class CurrentUserSerializer < UserSerializer class CurrentUserSerializer < UserSerializer
attributes :signed_in, :permissions attributes :signed_in, :permissions, :status
def signed_in def signed_in
true true
......
...@@ -16,6 +16,8 @@ class PermissionsChecker ...@@ -16,6 +16,8 @@ class PermissionsChecker
# checking if user is trying to access users/rooms/recordings from different provider # checking if user is trying to access users/rooms/recordings from different provider
return false unless current_provider_check return false unless current_provider_check
# Make sure the user is not banned or pending
return false unless @current_user.active?
return true if RolePermission.joins(:permission).exists?( return true if RolePermission.joins(:permission).exists?(
role_id: @current_user.role_id, role_id: @current_user.role_id,
......
...@@ -31,7 +31,9 @@ module Greenlight ...@@ -31,7 +31,9 @@ module Greenlight
invite_token_invalid: 'InviteInvalid', invite_token_invalid: 'InviteInvalid',
hcaptcha_invalid: 'HCaptchaInvalid', hcaptcha_invalid: 'HCaptchaInvalid',
incorrect_old_password: 'IncorrectOldPassword', incorrect_old_password: 'IncorrectOldPassword',
room_limit: 'RoomLimitError' room_limit: 'RoomLimitError',
pending_user: 'PendingUser',
banned_user: 'BannedUser'
} }
ActiveModelSerializers.config.adapter = :json ActiveModelSerializers.config.adapter = :json
......
...@@ -35,6 +35,32 @@ RSpec.describe Api::V1::SessionsController, type: :controller do ...@@ -35,6 +35,32 @@ RSpec.describe Api::V1::SessionsController, type: :controller do
expect(cookies.encrypted[:_extended_session]['session_token']).to eq(user.reload.session_token) expect(cookies.encrypted[:_extended_session]['session_token']).to eq(user.reload.session_token)
expect(session[:session_token]).to eq(user.session_token) expect(session[:session_token]).to eq(user.session_token)
end end
it 'returns BannedUser error if the user is banned' do
banned_user = create(:user, password: 'Password1!', status: :banned)
post :create, params: {
session: {
email: banned_user.email,
password: 'Password1!'
}
}
expect(JSON.parse(response.body)['errors']).to eq('BannedUser')
end
it 'returns Pending error if the user is banned' do
banned_user = create(:user, password: 'Password1!', status: :pending)
post :create, params: {
session: {
email: banned_user.email,
password: 'Password1!'
}
}
expect(JSON.parse(response.body)['errors']).to eq('PendingUser')
end
end end
describe '#destroy' do describe '#destroy' do
......
...@@ -44,6 +44,18 @@ describe PermissionsChecker, type: :service do ...@@ -44,6 +44,18 @@ describe PermissionsChecker, type: :service do
).call).to be(true) ).call).to be(true)
end end
it 'returns false if the users status is not active' do
banned_user = create(:user, status: :banned)
expect(described_class.new(
current_user: banned_user,
permission_names: permission.name,
user_id: '',
friendly_id: '',
record_id: '',
current_provider: user.provider
).call).to be(false)
end
context 'multiple permission names' do context 'multiple permission names' do
let(:permission2) { create(:permission) } let(:permission2) { create(:permission) }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment