-
Notifications
You must be signed in to change notification settings - Fork 2
Auth #33
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,3 +34,5 @@ | |
/yarn-error.log | ||
yarn-debug.log* | ||
.yarn-integrity | ||
|
||
*.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Place all the styles related to the login controller here. | ||
// They will automatically be included in application.css. | ||
// You can use Sass (SCSS) here: https://sass-lang.com/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Place all the styles related to the register controller here. | ||
// They will automatically be included in application.css. | ||
// You can use Sass (SCSS) here: https://sass-lang.com/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,39 @@ | ||
class ApplicationController < ActionController::Base | ||
before_action :authorized | ||
SECRET_KEY = Rails.application.secrets.secret_key_base. to_s | ||
|
||
def encode_token(payload, exp = 2.hours.from_now) | ||
payload[:exp] = exp.to_i | ||
JWT.encode(payload, SECRET_KEY) | ||
end | ||
|
||
def auth_header | ||
request.headers['Authorization'] | ||
end | ||
|
||
def decoded_token | ||
if auth_header | ||
token = auth_header.split(' ')[1] | ||
begin | ||
JWT.decode(token, SECRET_KEY, true, algorithm: 'HS256') | ||
rescue JWT::DecodeError | ||
nil | ||
end | ||
end | ||
end | ||
|
||
def current_user | ||
if decoded_token | ||
user_id = decoded_token[0]['user_id'] | ||
@user = User.find_by(id: user_id) | ||
end | ||
end | ||
|
||
def logged_in? | ||
!!current_user | ||
end | ||
|
||
def authorized | ||
render json: { message: 'Please log in' }, status: :unauthorized unless logged_in? | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
class LoginController < ApplicationController | ||
skip_before_action :verify_authenticity_token, :authorized, only: [:create] | ||
|
||
def create | ||
@user = User.find_by(username: user_login_params[:username]) | ||
#User#authenticate comes from BCrypt | ||
if @user && @user.authenticate(user_login_params[:password]) | ||
@token = encode_token({ user_id: @user.id }) | ||
time = Time.now + 2.hours.to_i | ||
render json: { user: UserSerializer.new(@user), jwt: @token, exp: time }, status: :accepted | ||
else | ||
render json: { message: 'Invalid username or password' }, status: :unauthorized | ||
end | ||
end | ||
|
||
private | ||
def user_login_params | ||
params.require(:user).permit(:username, :password) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class RegisterController < ApplicationController | ||
skip_before_action :verify_authenticity_token, :authorized, only: [:create] | ||
|
||
def create | ||
if User.exists?(username: user_params[:username]) | ||
render json: { error: 'Username taken'}, status: 409 | ||
return | ||
end | ||
@user = User.create(user_params) | ||
if @user.valid? | ||
@token = encode_token({ user_id: @user.id }) | ||
time = Time.now + 2.hours.to_i | ||
render json: { user: UserSerializer.new(@user), jwt: @token, exp: time }, status: :created | ||
Comment on lines
+11
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to clarify the intent here, but is the reason why you're returning a JWT token here as well because when a user registers, it should also automatically log them in? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is how the behavior is now just so you don't need to take two steps. It can easily be changed later if we don't want that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like it the way you did it. Just making sure I'm understanding it correctly |
||
else | ||
render json: { errors: @user.errors.full_messages }, status: :unprocessable_entity | ||
end | ||
end | ||
|
||
private | ||
def user_params | ||
params.require(:user).permit(:username, :password, :role) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module LoginHelper | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module RegisterHelper | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
class User < ApplicationRecord | ||
enum role: [:buyer, :seller] | ||
validates :username, presence: true | ||
validates :password, presence: true | ||
validates :role, presence: true | ||
has_secure_password | ||
enum role: [:buyer, :seller] | ||
validates :username, presence: true, uniqueness: { case_sensitive: false } | ||
validates :role, presence: true | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class UserSerializer < ActiveModel::Serializer | ||
attributes :username, :role | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Rails.application.config.middleware.insert_before 0, Rack::Cors do | ||
allow do | ||
# Change to frontend domain | ||
origins '*' | ||
resource '*', headers: :any, methods: :any | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
class RemoveQuantityFromDoughnuts < ActiveRecord::Migration[6.1] | ||
def change | ||
remove_column :doughnuts, :quantity, :float | ||
# remove_column :doughnuts, :quantity, :float | ||
end | ||
end |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
require "test_helper" | ||
|
||
class LoginControllerTest < ActionDispatch::IntegrationTest | ||
# test "the truth" do | ||
# assert true | ||
# end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
require "test_helper" | ||
|
||
class RegisterControllerTest < ActionDispatch::IntegrationTest | ||
# test "the truth" do | ||
# assert true | ||
# end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will require the frontend to send a JSON object in the following format:
Nothing wrong with this functionality-wise, but just making sure that this is how you want it to be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that is how I wrote it and tested it. We can just accept the username and password instead of a user json if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This way is fine. We just have to make sure the frontend people know the POST body should look like this for login