-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added api v1 endpoints for user login
- Loading branch information
Showing
9 changed files
with
261 additions
and
2 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 |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
module Api | ||
module V1 | ||
class BaseController < ApplicationController | ||
protect_from_forgery with: :null_session | ||
|
||
private | ||
|
||
def page_not_found | ||
render json: { errors: ['Not found'] }, status: :not_found | ||
end | ||
|
||
def authentication_error | ||
render json: { errors: [t('controllers.authentication.permission')] }, status: :unauthorized | ||
end | ||
|
||
def confirmation_error | ||
render json: { errors: [t('controllers.confirmation.permission')] }, status: :unauthorized | ||
end | ||
|
||
def ban_error | ||
render json: { errors: [t('controllers.confirmation.ban')] }, status: :unauthorized | ||
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,42 @@ | ||
# frozen_string_literal: true | ||
|
||
module Api | ||
module V1 | ||
module Users | ||
class AccessTokensController < Api::V1::BaseController | ||
include Deps[generate_token: 'services.auth.generate_token'] | ||
|
||
skip_before_action :authenticate, only: %i[create] | ||
skip_before_action :check_email_confirmation, only: %i[create] | ||
skip_before_action :check_email_ban, only: %i[create] | ||
|
||
before_action :find_user, only: %i[create] | ||
before_action :authenticate_user, only: %i[create] | ||
|
||
def create | ||
render json: { access_token: generate_token.call(user: @user)[:result] }, status: :created | ||
end | ||
|
||
private | ||
|
||
def find_user | ||
@user = User.not_banned.find_by!(email: user_params[:email]&.strip&.downcase) | ||
end | ||
|
||
def authenticate_user | ||
return if @user.authenticate(user_params[:password]) | ||
|
||
failed_sign_in | ||
end | ||
|
||
def failed_sign_in | ||
render json: { errors: [t('controllers.users.sessions.invalid')] }, status: :bad_request | ||
end | ||
|
||
def user_params | ||
params.require(:user).permit(:email, :password) | ||
end | ||
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,32 @@ | ||
# frozen_string_literal: true | ||
|
||
module Api | ||
module V1 | ||
class UsersController < Api::V1::BaseController | ||
include Deps[ | ||
generate_token: 'services.auth.generate_token', | ||
create_form: 'forms.users.create' | ||
] | ||
|
||
skip_before_action :authenticate, only: %i[create] | ||
skip_before_action :check_email_confirmation, only: %i[create] | ||
skip_before_action :check_email_ban, only: %i[create] | ||
|
||
def create | ||
case create_form.call(params: user_params.to_h.symbolize_keys) | ||
in { errors: errors } then render json: { errors: errors }, status: :bad_request | ||
in { result: result } | ||
render json: { access_token: generate_token.call(user: result)[:result] }, status: :created | ||
end | ||
end | ||
|
||
private | ||
|
||
def user_params | ||
params_hash = params.require(:user).permit(:email, :password, :password_confirmation) | ||
params_hash[:email] = params_hash[:email].strip.downcase | ||
params_hash | ||
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
76 changes: 76 additions & 0 deletions
76
spec/controllers/api/v1/users/access_tokens_controller_spec.rb
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,76 @@ | ||
# frozen_string_literal: true | ||
|
||
describe Api::V1::Users::AccessTokensController do | ||
describe 'POST#create' do | ||
context 'for unexisting user' do | ||
it 'returns error', :aggregate_failures do | ||
post :create, params: { user: { email: '[email protected]', password: '1' } } | ||
|
||
expect(response).to have_http_status :not_found | ||
expect(response.parsed_body['access_token']).to be_blank | ||
end | ||
end | ||
|
||
context 'for existing user' do | ||
let!(:user) { create :user } | ||
|
||
context 'for unconfirmed email' do | ||
before { user.update!(confirmed_at: nil) } | ||
|
||
it 'returns access token', :aggregate_failures do | ||
post :create, params: { user: { email: user.email.upcase, password: user.password } } | ||
|
||
expect(response).to have_http_status :created | ||
expect(response.parsed_body['access_token']).not_to be_blank | ||
end | ||
end | ||
|
||
context 'for invalid password' do | ||
it 'returns error', :aggregate_failures do | ||
post :create, params: { user: { email: user.email, password: 'invalid_password' } } | ||
|
||
expect(response).to have_http_status :bad_request | ||
expect(response.parsed_body['access_token']).to be_blank | ||
end | ||
end | ||
|
||
context 'for empty password' do | ||
it 'returns error', :aggregate_failures do | ||
post :create, params: { user: { email: user.email, password: '' } } | ||
|
||
expect(response).to have_http_status :bad_request | ||
expect(response.parsed_body['access_token']).to be_blank | ||
end | ||
end | ||
|
||
context 'for valid password' do | ||
it 'returns access token', :aggregate_failures do | ||
post :create, params: { user: { email: user.email, password: user.password } } | ||
|
||
expect(response).to have_http_status :created | ||
expect(response.parsed_body['access_token']).not_to be_blank | ||
end | ||
end | ||
|
||
context 'for valid password and upcased email' do | ||
it 'returns access token', :aggregate_failures do | ||
post :create, params: { user: { email: user.email.upcase, password: user.password } } | ||
|
||
expect(response).to have_http_status :created | ||
expect(response.parsed_body['access_token']).not_to be_blank | ||
end | ||
|
||
context 'for banned user' do | ||
before { user.update!(banned_at: DateTime.now) } | ||
|
||
it 'returns error', :aggregate_failures do | ||
post :create, params: { user: { email: user.email.upcase, password: user.password } } | ||
|
||
expect(response).to have_http_status :not_found | ||
expect(response.parsed_body['access_token']).to be_blank | ||
end | ||
end | ||
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,65 @@ | ||
# frozen_string_literal: true | ||
|
||
describe Api::V1::UsersController do | ||
describe 'POST#create' do | ||
context 'for invalid credentials' do | ||
let(:request) { post :create, params: { user: { email: '', password: '1' } } } | ||
|
||
it 'does not create user', :aggregate_failures do | ||
expect { request }.not_to change(User, :count) | ||
expect(response).to have_http_status :bad_request | ||
end | ||
end | ||
|
||
context 'for short password' do | ||
let(:request) { post :create, params: { user: { email: '[email protected]', password: '1' } } } | ||
|
||
it 'does not create new user', :aggregate_failures do | ||
expect { request }.not_to change(User, :count) | ||
expect(response).to have_http_status :bad_request | ||
end | ||
end | ||
|
||
context 'without password confirmation' do | ||
let(:request) { post :create, params: { user: { email: '[email protected]', password: '12345678' } } } | ||
|
||
it 'does not create new user', :aggregate_failures do | ||
expect { request }.not_to change(User, :count) | ||
expect(response).to have_http_status :bad_request | ||
end | ||
end | ||
|
||
context 'for existing user' do | ||
let!(:user) { create :user } | ||
let(:request) { | ||
post :create, params: { user: { email: user.email, password: '12345678', password_confirmation: '12345678' } } | ||
} | ||
|
||
it 'does not create new user', :aggregate_failures do | ||
expect { request }.not_to change(User, :count) | ||
expect(response).to have_http_status :bad_request | ||
end | ||
end | ||
|
||
context 'for valid data' do | ||
let(:user_params) { { email: ' [email protected] ', password: '12345678', password_confirmation: '12345678' } } | ||
let(:request) { post :create, params: { user: user_params } } | ||
|
||
it 'creates new user', :aggregate_failures do | ||
expect { request }.to change(User, :count).by(1) | ||
expect(User.last.email).to eq '[email protected]' | ||
expect(response).to have_http_status :created | ||
expect(response.parsed_body['access_token']).not_to be_blank | ||
end | ||
|
||
context 'for banned email' do | ||
before { create :banned_email, value: '[email protected]' } | ||
|
||
it 'does not create new user', :aggregate_failures do | ||
expect { request }.not_to change(User, :count) | ||
expect(response).to have_http_status :bad_request | ||
end | ||
end | ||
end | ||
end | ||
end |