diff --git a/.gitignore b/.gitignore index 050c9d95c..bc1b7b334 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,11 @@ # Ignore bundler config. /.bundle +# Hide the .env. It's full of secrets! +.env + +.DS_Store + # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal diff --git a/Gemfile b/Gemfile index e87fad5fc..da23e76fc 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,10 @@ source 'https://rubygems.org' +gem "omniauth" +gem "omniauth-github" + +gem "awesome_print" # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '4.2.7' # Use sqlite3 as the database for Active Record @@ -35,6 +39,8 @@ gem 'sdoc', '~> 0.4.0', group: :doc group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' + gem 'dotenv-rails' + gem 'better_errors' end group :development do @@ -44,4 +50,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' end - +# +# group :test do +# gem 'minitest-reporters' +# end diff --git a/Gemfile.lock b/Gemfile.lock index 187046034..f52268aa1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -37,10 +37,16 @@ GEM thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) arel (6.0.3) + awesome_print (1.7.0) + better_errors (2.1.1) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + rack (>= 0.9.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) builder (3.2.2) byebug (9.0.5) + coderay (1.1.1) coffee-rails (4.1.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.1.x) @@ -50,10 +56,17 @@ GEM coffee-script-source (1.10.0) concurrent-ruby (1.0.2) debug_inspector (0.0.2) + dotenv (2.1.1) + dotenv-rails (2.1.1) + dotenv (= 2.1.1) + railties (>= 4.0, < 5.1) erubis (2.7.0) execjs (2.7.0) + faraday (0.9.2) + multipart-post (>= 1.2, < 3) globalid (0.3.7) activesupport (>= 4.1.0) + hashie (3.4.6) i18n (0.7.0) jbuilder (2.6.0) activesupport (>= 3.0.0, < 5.1) @@ -63,6 +76,7 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (1.8.3) + jwt (1.5.6) loofah (2.0.3) nokogiri (>= 1.5.9) mail (2.6.4) @@ -73,9 +87,26 @@ GEM mini_portile2 (2.1.0) minitest (5.9.1) multi_json (1.12.1) + multi_xml (0.5.5) + multipart-post (2.0.0) nokogiri (1.6.8) mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) + oauth2 (1.2.0) + faraday (>= 0.8, < 0.10) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.3.1) + hashie (>= 1.2, < 4) + rack (>= 1.0, < 3) + omniauth-github (1.1.2) + omniauth (~> 1.0) + omniauth-oauth2 (~> 1.1) + omniauth-oauth2 (1.4.0) + oauth2 (~> 1.0) + omniauth (~> 1.2) pkg-config (1.1.7) rack (1.6.4) rack-test (0.6.3) @@ -146,10 +177,15 @@ PLATFORMS ruby DEPENDENCIES + awesome_print + better_errors byebug coffee-rails (~> 4.1.0) + dotenv-rails jbuilder (~> 2.0) jquery-rails + omniauth + omniauth-github rails (= 4.2.7) sass-rails (~> 5.0) sdoc (~> 0.4.0) @@ -160,4 +196,4 @@ DEPENDENCIES web-console (~> 2.0) BUNDLED WITH - 1.13.1 + 1.13.2 diff --git a/app/assets/javascripts/homepages.coffee b/app/assets/javascripts/homepages.coffee new file mode 100644 index 000000000..24f83d18b --- /dev/null +++ b/app/assets/javascripts/homepages.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/sessions.coffee b/app/assets/javascripts/sessions.coffee new file mode 100644 index 000000000..24f83d18b --- /dev/null +++ b/app/assets/javascripts/sessions.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss new file mode 100644 index 000000000..e42583ae8 --- /dev/null +++ b/app/assets/stylesheets/homepages.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the homepages controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 000000000..7bef9cf82 --- /dev/null +++ b/app/assets/stylesheets/sessions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sessions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb new file mode 100644 index 000000000..033bf5597 --- /dev/null +++ b/app/controllers/homepages_controller.rb @@ -0,0 +1,12 @@ +class HomepagesController < ApplicationController + + def index + get_current_user + end + + private + def get_current_user + @user = User.find_by(id: session[:user_id]) + end + +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 000000000..563f37a66 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,30 @@ +class SessionsController < ApplicationController + + def create + auth_hash = request.env['omniauth.auth'] + redirect to login_failure_path unless auth_hash['uid'] + + @user = User.find_by(uid: auth_hash[:uid], provider: 'github') + if @user.nil? + # User doesn't match anything in the DB. + # Attempt to create a new user. + @user = User.build_from_github(auth_hash) + render :creation_failure unless @user.save + end + + # Save the user ID in the session + session[:user_id] = @user.id + + redirect_to index_path + end + + def index + @user = User.find(session[:user_id]) # < recalls the value set in a previous request + end + + def destroy + session[:user_id] = nil + redirect_to root_path + end + +end diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb index c64be141e..9fd4f83cc 100644 --- a/app/controllers/tasks_controller.rb +++ b/app/controllers/tasks_controller.rb @@ -1,6 +1,7 @@ class TasksController < ApplicationController def index - @tasks = Task.all + @tasks = Task.where(user_id: session[:user_id]) + @user = User.find(session[:user_id]) end def new @@ -24,8 +25,8 @@ def edit def update @mytask = Task.find(params[:id].to_i) @params = params - @mytask.task_name = params[:task_name] - @mytask.description = params[:description] + @mytask.task_name = params[:task][:task_name] + @mytask.description = params[:task][:description] @mytask.save redirect_to action: "index" @@ -34,10 +35,11 @@ def update def create @params = params @mytask = Task.new - @mytask.task_name = params[:task_name] - @mytask.description = params[:description] + @mytask.task_name = params[:task][:task_name] + @mytask.description = params[:task][:description] @mytask.completion_status = "incomplete" @mytask.completion_date = "Not completed yet!" + @mytask.user_id = session[:user_id] @mytask.save redirect_to action: "index" @@ -64,7 +66,7 @@ def mark_incomplete private def user_params - params.require(:task).permit(:task_name, :description, :completion_status, :completeion_date) + params.require(:task).permit(:task_name, :description, :completion_status, :completion_date) end end diff --git a/app/helpers/homepages_helper.rb b/app/helpers/homepages_helper.rb new file mode 100644 index 000000000..4bd8098f3 --- /dev/null +++ b/app/helpers/homepages_helper.rb @@ -0,0 +1,2 @@ +module HomepagesHelper +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb new file mode 100644 index 000000000..309f8b2eb --- /dev/null +++ b/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 000000000..f6c13853a --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,13 @@ +class User < ActiveRecord::Base + validates :email, :uid, :provider, presence: true + +def self.build_from_github(auth_hash) + user = User.new + user.uid = auth_hash[:uid] + user.provider = 'github' + user.name = auth_hash['info']['name'] + user.email = auth_hash['info']['email'] + + return user +end +end diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb new file mode 100644 index 000000000..7ba3ae900 --- /dev/null +++ b/app/views/homepages/index.html.erb @@ -0,0 +1,9 @@ +<% if @user %> +

Welcome <%= @user.name %>!

+<% else %> +

Please log in

+<% end %> + +<% if flash[:notice] %> +

<%= flash[:notice] %>

+<% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 34310a61d..93c923c4e 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,6 +9,13 @@

Task List

+ <% if session[:user_id] == nil %> +

<%= link_to "log in via github", "/auth/github" %>

+ <% else %> +

<%= link_to "logout", sessions_destroy_path,:method => :delete %>

+ +

<%= link_to "View my Tasks", index_path %>

+ <% end %>
<%= yield %> diff --git a/app/views/sessions/create.html.erb b/app/views/sessions/create.html.erb new file mode 100644 index 000000000..00c31cf79 --- /dev/null +++ b/app/views/sessions/create.html.erb @@ -0,0 +1 @@ +

Sessions#create

diff --git a/app/views/tasks/_form.html.erb b/app/views/tasks/_form.html.erb new file mode 100644 index 000000000..1078142c6 --- /dev/null +++ b/app/views/tasks/_form.html.erb @@ -0,0 +1,10 @@ +<%= form_for @mytask, url: action_name do |f| %> + + <%= f.label :task_name %> + <%= f.text_field :task_name %> + + <%= f.label :description %> + <%= f.text_area :description %> + + <%= f.submit %> +<% end %> diff --git a/app/views/tasks/edit.html.erb b/app/views/tasks/edit.html.erb index e5260aaa6..dd3c248f7 100644 --- a/app/views/tasks/edit.html.erb +++ b/app/views/tasks/edit.html.erb @@ -1,5 +1,5 @@

Edit Your Task

- + + +<%= render partial: "form", locals: { action_name: "create"} %> diff --git a/app/views/tasks/index.html.erb b/app/views/tasks/index.html.erb index 544a119aa..14875d100 100644 --- a/app/views/tasks/index.html.erb +++ b/app/views/tasks/index.html.erb @@ -1,22 +1,26 @@ +

Welcome <%= @user.name %>!

+

Get to work!

<% @tasks.each do |task| %> -
-

<%= link_to( task.task_name, show_path(task.id)) %>

+ + + - <% if task.completion_status == 'incomplete' %> -

<%= button_to 'mark as complete', {action: "mark_complete", id: task.id }, - method: :mark_complete %>

- <% else %> -

<%= button_to 'mark as incomplete', {action: "mark_incomplete", id: task.id }, - method: :mark_incomplete %>

- <% end %> + <% if task.completion_status == 'incomplete' %> + + <% else %> + + <% end %> -

<%= button_to 'edit task', {action: "edit", id: task.id }, - method: :edit %>

+ -

<%= button_to 'delete task', {action: "delete", id: task.id }, - method: :delete, data: {confirm: "Are you sure you want to delete this task?"} %>

- + + +

<%= link_to( task.task_name, show_path(task.id)) %>

<%= button_to 'mark as complete', {action: "mark_complete", id: task.id }, + method: :mark_complete %> <%= button_to 'mark as incomplete', {action: "mark_incomplete", id: task.id }, + method: :mark_incomplete %> <%= button_to 'edit task', {action: "edit", id: task.id }, + method: :edit %> <%= button_to 'delete task', {action: "delete", id: task.id }, + method: :delete, data: {confirm: "Are you sure you want to delete this task?"} %>
<% end %>
diff --git a/app/views/tasks/new.html.erb b/app/views/tasks/new.html.erb index 069fd3116..faf2bade1 100644 --- a/app/views/tasks/new.html.erb +++ b/app/views/tasks/new.html.erb @@ -1,6 +1,6 @@

Make a new task!

-
+ + +<%= render partial: "form" , locals: { action_name: "create"}%> diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 000000000..fd4416122 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,3 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email" +end diff --git a/config/routes.rb b/config/routes.rb index fdc4d3724..a9de6b90d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ Rails.application.routes.draw do -root to: 'tasks#index' +root to: 'homepages#index' get 'tasks/index' => 'tasks#index', as: 'index' @@ -20,6 +20,16 @@ post 'tasks/create' => 'tasks#create', as: 'create' + # get 'sessions/create' + + get 'sessions/create' + + delete 'sessions/destroy' + + get "/auth/:provider/callback" => "sessions#create" + + get 'homepages/index' + # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". diff --git a/db/migrate/20161018170107_create_users.rb b/db/migrate/20161018170107_create_users.rb new file mode 100644 index 000000000..f85251a60 --- /dev/null +++ b/db/migrate/20161018170107_create_users.rb @@ -0,0 +1,12 @@ +class CreateUsers < ActiveRecord::Migration + def change + create_table :users do |t| + t.string :uid + t.string :name + t.string :provider + t.string :email + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20161026071831_add_user_id_column_to_task.rb b/db/migrate/20161026071831_add_user_id_column_to_task.rb new file mode 100644 index 000000000..3f7114b0c --- /dev/null +++ b/db/migrate/20161026071831_add_user_id_column_to_task.rb @@ -0,0 +1,5 @@ +class AddUserIdColumnToTask < ActiveRecord::Migration + def change + add_column :tasks, :user_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index ff400f0a2..e5dfc62f7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160930215941) do +ActiveRecord::Schema.define(version: 20161026071831) do create_table "tasks", force: :cascade do |t| t.string "task_name" @@ -20,6 +20,16 @@ t.datetime "completion_date" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "user_id" + end + + create_table "users", force: :cascade do |t| + t.string "uid" + t.string "name" + t.string "provider" + t.string "email" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end end diff --git a/test/controllers/homepages_controller_test.rb b/test/controllers/homepages_controller_test.rb new file mode 100644 index 000000000..46828ab12 --- /dev/null +++ b/test/controllers/homepages_controller_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class HomepagesControllerTest < ActionController::TestCase + test "should get index" do + get :index + assert_response :success + end + +end diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 000000000..afdd8c3b3 --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,34 @@ +require 'test_helper' + +class SessionsControllerTest < ActionController::TestCase + test "should get create" do + get :create + assert_response :success + end + + def login_a_user + request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:github] + get :create, {provider: "github"} + end + + test "Can Create a user" do + assert_difference('User.count', 1) do + login_a_user + assert_response :redirect + assert_redirected_to root_path + asser_equal session[:user_id], User.find_by(uid: OmniAuth.config.mock_auth[:github][:uid], provider: "github").id + end + end + + test "If a user logs in twice it doesn't create a 2nd user" do + assert_difference('User.count', 1) do + login_a_user + end + assert_no_difference('User.count') do + login_a_user + assert_response :redirect + assert_redirected_to root_path + end + end + +end diff --git a/test/controllers/tasks_controller_test.rb b/test/controllers/tasks_controller_test.rb index fd0792be8..627f9d225 100644 --- a/test/controllers/tasks_controller_test.rb +++ b/test/controllers/tasks_controller_test.rb @@ -1,6 +1,22 @@ require 'test_helper' class TasksControllerTest < ActionController::TestCase + + test "Make sure a user can see his/her/their task" do + session[:user_id] = users(:ada).id + get :show, id: tasks(:adas_task).id + + assert_response :success + end + + test "Make sure a user cannot see another user's task" do + session[:user_id] = users(:ada).id + get :show, id: tasks(:babbages_task).id + + assert_response :redirect + assert_equal flash[:notice], "You do not have access to that task." + end + test "should get index" do get :index assert_response :success diff --git a/test/fixtures/tasks.yml b/test/fixtures/tasks.yml index 2971a9b8e..0b46d61fb 100644 --- a/test/fixtures/tasks.yml +++ b/test/fixtures/tasks.yml @@ -1,13 +1,12 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - task_name: MyString - description: MyText - completion_status: MyString - completion_date: MyString +adas_task: + task_name: "write first code!" + description: "Fortran" + completion_status: complete + completion_date: 2016-09-15 -two: - task_name: MyString - description: MyText - completion_status: MyString - completion_date: MyString +babbages_task: + task_name: "make first computer" + description: "build it!" + completion_status: Incomplete diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 000000000..08b2857a3 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,17 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +ada: + id: 1 + uid: 11234 + name: "Helena Helga" + provider: github + email: "hh@self.com" + created_at: 2016-08-13 14:15:56 + +babbage: + id: 2 + uid: 12344 + name: "Gerdy Lurdy" + provider: github + email: "gl@self.com" + created_at: 2016-08-13 14:15:56 diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 000000000..320ca4d1b --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,19 @@ +require 'test_helper' + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end + + test "test validity of user if email, uid, and provider not present" do + user = User.new + assert_not user.valid? + user.email = "joe@schmoe.com" + assert_not user.valid? + user.uid = 12 + assert_not user.valid? + user.provider = "github" + assert user.valid? + end + +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 92e39b2d7..2af1c951b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,10 +1,26 @@ ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' +# require 'minitest-reporters' class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. fixtures :all # Add more helper methods to be used by all tests here... + + # /test/test_helper.rb + def setup + # Once you have enabled test mode, all requests + # to OmniAuth will be short circuited to use the mock authentication hash. + # A request to /auth/provider will redirect immediately to /auth/provider/callback. + OmniAuth.config.test_mode = true + + # The mock_auth configuration allows you to set per-provider (or default) authentication + # hashes to return during testing. + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new({ + provider: 'github', uid: '123545', info: { email: "a@b.com", name: "Ada" } + }) + end + end