diff --git a/.gitignore b/.gitignore index 48fb168f..5a111e4e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ # Ignore Byebug command history file. .byebug_history + +.env diff --git a/Gemfile b/Gemfile index 42f4bb2c..239ff8c1 100644 --- a/Gemfile +++ b/Gemfile @@ -34,6 +34,10 @@ gem 'jbuilder', '~> 2.5' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development +gem "omniauth" +gem "omniauth-github" + + gem 'bootstrap', '~> 4.1.3' group :development, :test do @@ -62,6 +66,7 @@ group :development do # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' + gem 'dotenv-rails' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem diff --git a/Gemfile.lock b/Gemfile.lock index 5b407e7e..f66ae74f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -70,11 +70,18 @@ GEM concurrent-ruby (1.0.5) crass (1.0.4) debug_inspector (0.0.3) + dotenv (2.5.0) + dotenv-rails (2.5.0) + dotenv (= 2.5.0) + railties (>= 3.2, < 6.0) erubi (1.7.1) execjs (2.7.0) + faraday (0.15.3) + multipart-post (>= 1.2, < 3) ffi (1.9.25) globalid (0.4.1) activesupport (>= 4.2.0) + hashie (3.5.7) i18n (1.1.0) concurrent-ruby (~> 1.0) jbuilder (2.7.0) @@ -84,6 +91,7 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + jwt (2.1.0) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -113,9 +121,26 @@ GEM minitest (~> 5.0) rails (>= 4.1) multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) nio4r (2.3.1) nokogiri (1.8.4) mini_portile2 (~> 2.3.0) + oauth2 (1.4.1) + faraday (>= 0.8, < 0.16.0) + jwt (>= 1.0, < 3.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.8.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.5.0) + oauth2 (~> 1.1) + omniauth (~> 1.2) pg (0.21.0) popper_js (1.14.3) pry (0.11.3) @@ -207,6 +232,7 @@ DEPENDENCIES bootstrap (~> 4.1.3) byebug coffee-rails (~> 4.2) + dotenv-rails jbuilder (~> 2.5) jquery-rails listen (~> 3.0.5) @@ -214,6 +240,8 @@ DEPENDENCIES minitest-reporters minitest-skip minitest-spec-rails + omniauth + omniauth-github pg (~> 0.18) pry-rails puma (~> 3.0) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c12c7c17..1785fe52 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,15 +3,24 @@ class ApplicationController < ActionController::Base before_action :find_user + def render_404 # DPR: this will actually render a 404 page in production raise ActionController::RoutingError.new('Not Found') end -private + private + def find_user if session[:user_id] - @login_user = User.find_by(id: session[:user_id]) + @user = User.find_by(id: session[:user_id]) + end + end + + def require_login + if find_user.nil? + flash[:result_text] = "You must be logged in to view this section" + redirect_to root_path end end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 5bce99e6..d9894c91 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -2,33 +2,47 @@ class SessionsController < ApplicationController def login_form end - def login - username = params[:username] - if username and user = User.find_by(username: username) - session[:user_id] = user.id - flash[:status] = :success - flash[:result_text] = "Successfully logged in as existing user #{user.username}" + + def create + auth_hash = request.env['omniauth.auth'] + + user = User.find_by(uid: auth_hash[:uid], provider: 'github') + if user + # User was found in the database + flash[:result_text] = "Logged in as returning user #{user.username}" + else - user = User.new(username: username) + # User doesn't match anything in the DB + # Attempt to create a new user + user = User.build_from_github(auth_hash) + if user.save - session[:user_id] = user.id - flash[:status] = :success - flash[:result_text] = "Successfully created new user #{user.username} with ID #{user.id}" + flash[:result_text] = "Logged in as new user #{user.username}" + else - flash.now[:status] = :failure - flash.now[:result_text] = "Could not log in" - flash.now[:messages] = user.errors.messages - render "login_form", status: :bad_request + # Couldn't save the user for some reason. If we + # hit this it probably means there's a bug with the + # way we've configured GitHub. Our strategy will + # be to display error messages to make future + # debugging easier. + + flash[:result_text] = "Could not create new user account: #{user.errors.messages}" + redirect_to root_path return end end + + # If we get here, we have a valid user instance + session[:user_id] = user.id redirect_to root_path end - def logout - session[:user_id] = nil - flash[:status] = :success - flash[:result_text] = "Successfully logged out" + def destroy + if @user + session[:user_id] = nil + flash[:result_text] = "Successfully logged out!" + end redirect_to root_path end + end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 73b42652..58882c35 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,10 +1,17 @@ class UsersController < ApplicationController + before_action :require_login + def index - @users = User.all + + @users = User.all + end def show - @user = User.find_by(id: params[:id]) - render_404 unless @user + unless @user.id == params[:id].to_i + flash[:result_text] = "Not allowed." + redirect_to root_path + end end + end diff --git a/app/controllers/works_controller.rb b/app/controllers/works_controller.rb index 2020bee4..081a8b5f 100644 --- a/app/controllers/works_controller.rb +++ b/app/controllers/works_controller.rb @@ -2,6 +2,8 @@ class WorksController < ApplicationController # We should always be able to tell what category # of work we're dealing with before_action :category_from_work, except: [:root, :index, :new, :create] + # before_action :find_user, except: [:root] + before_action :require_login, except: [:root] def root @albums = Work.best_albums @@ -11,11 +13,12 @@ def root end def index - @works_by_category = Work.to_category_hash + + @works_by_category = Work.to_category_hash end def new - @work = Work.new + @work = Work.new end def create @@ -34,23 +37,25 @@ def create end def show - @votes = @work.votes.order(created_at: :desc) + @votes = @work.votes.order(created_at: :desc) end def edit end def update + @work.update_attributes(media_params) if @work.save flash[:status] = :success flash[:result_text] = "Successfully updated #{@media_category.singularize} #{@work.id}" redirect_to work_path(@work) - else + + elsif @work && !@work.valid? flash.now[:status] = :failure flash.now[:result_text] = "Could not update #{@media_category.singularize}" flash.now[:messages] = @work.errors.messages - render :edit, status: :not_found + render :edit, status: :bad_request end end @@ -63,8 +68,8 @@ def destroy def upvote flash[:status] = :failure - if @login_user - vote = Vote.new(user: @login_user, work: @work) + + vote = Vote.new(user: @user, work: @work) if vote.save flash[:status] = :success flash[:result_text] = "Successfully upvoted!" @@ -72,9 +77,6 @@ def upvote flash[:result_text] = "Could not upvote" flash[:messages] = vote.errors.messages end - else - flash[:result_text] = "You must log in to do that" - end # Refresh the page to show either the updated vote count # or the error message diff --git a/app/models/user.rb b/app/models/user.rb index 4cac8fe0..c33a80f8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,4 +3,18 @@ class User < ApplicationRecord has_many :ranked_works, through: :votes, source: :work validates :username, uniqueness: true, presence: true + # validates :uid, presence: true + # validates :provider, presence: true + + def self.build_from_github(auth_hash) + user = User.new + user.uid = auth_hash[:uid] + user.provider = 'github' + user.username = auth_hash[:info][:name] + user.email = auth_hash[:info][:email] + + # Note that the user has not been saved + return user + end + end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index e7b07ce4..bc7cabcc 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -33,19 +33,20 @@