From b85344c02570d9c538272bfc5876b2bf071b9dca Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 19:13:49 +0100 Subject: [PATCH 01/20] files setup --- Gemfile | 7 +++ Gemfile.lock | 28 +++++++++ app.rb | 17 ++++++ config.ru | 3 + lib/database_connection.rb | 38 ++++++++++++ lib/peep.rb | 3 + lib/peep_repository.rb | 5 ++ lib/user.rb | 3 + lib/user_repository.rb | 5 ++ spec/app_spec.rb | 27 +++++++++ spec/peep_repository_spec.rb | 14 +++++ spec/seeds/peeps_seeds.sql | 17 ++++++ spec/seeds/users_seeds.sql | 15 +++++ spec/spec_helper.rb | 108 +++++++++++++++++++++++++++++++++++ spec/user_repository_spec.rb | 14 +++++ views/index.erb | 0 views/login.erb | 0 views/logout.erb | 0 views/new_peep.erb | 0 views/signup.erb | 0 20 files changed, 304 insertions(+) create mode 100644 app.rb create mode 100644 config.ru create mode 100644 lib/database_connection.rb create mode 100644 lib/peep.rb create mode 100644 lib/peep_repository.rb create mode 100644 lib/user.rb create mode 100644 lib/user_repository.rb create mode 100644 spec/app_spec.rb create mode 100644 spec/peep_repository_spec.rb create mode 100644 spec/seeds/peeps_seeds.sql create mode 100644 spec/seeds/users_seeds.sql create mode 100644 spec/user_repository_spec.rb create mode 100644 views/index.erb create mode 100644 views/login.erb create mode 100644 views/logout.erb create mode 100644 views/new_peep.erb create mode 100644 views/signup.erb diff --git a/Gemfile b/Gemfile index b1a320395a..74fa8fecab 100644 --- a/Gemfile +++ b/Gemfile @@ -11,3 +11,10 @@ end group :development, :test do gem 'rubocop', '1.20' end + +gem "sinatra", "~> 3.0" +gem "sinatra-contrib", "~> 3.0" +gem "webrick", "~> 1.8" +gem "rack-test", "~> 2.1" + +gem "pg", "~> 1.4" diff --git a/Gemfile.lock b/Gemfile.lock index 66064703c7..a19258200f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,9 +5,18 @@ GEM ast (2.4.2) diff-lcs (1.4.4) docile (1.4.0) + multi_json (1.15.0) + mustermann (3.0.0) + ruby2_keywords (~> 0.0.1) parallel (1.20.1) parser (3.0.2.0) ast (~> 2.4.1) + pg (1.4.6) + rack (2.2.6.4) + rack-protection (3.0.6) + rack + rack-test (2.1.0) + rack (>= 1.3) rainbow (3.0.0) regexp_parser (2.1.1) rexml (3.2.5) @@ -36,6 +45,7 @@ GEM rubocop-ast (1.11.0) parser (>= 3.0.1.1) ruby-progressbar (1.11.0) + ruby2_keywords (0.0.5) simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) @@ -46,18 +56,36 @@ GEM terminal-table simplecov-html (0.12.3) simplecov_json_formatter (0.1.3) + sinatra (3.0.6) + mustermann (~> 3.0) + rack (~> 2.2, >= 2.2.4) + rack-protection (= 3.0.6) + tilt (~> 2.0) + sinatra-contrib (3.0.6) + multi_json + mustermann (~> 3.0) + rack-protection (= 3.0.6) + sinatra (= 3.0.6) + tilt (~> 2.0) terminal-table (3.0.1) unicode-display_width (>= 1.1.1, < 3) + tilt (2.1.0) unicode-display_width (2.0.0) + webrick (1.8.1) PLATFORMS ruby DEPENDENCIES + pg (~> 1.4) + rack-test (~> 2.1) rspec rubocop (= 1.20) simplecov simplecov-console + sinatra (~> 3.0) + sinatra-contrib (~> 3.0) + webrick (~> 1.8) RUBY VERSION ruby 3.0.2p107 diff --git a/app.rb b/app.rb new file mode 100644 index 0000000000..52e69e9099 --- /dev/null +++ b/app.rb @@ -0,0 +1,17 @@ +require 'sinatra/base' +require 'sinatra/reloader' +require_relative 'lib/database_connection' +require_relative 'lib/user_repository' +require_relative 'lib/peep_repository' + +DatabaseConnection.connect + +class Application < Sinatra::Base + # This allows the app code to refresh + # without having to restart the server. + configure :development do + register Sinatra::Reloader + also_reload 'lib/user_repository' + also_reload 'lib/peep_repository' + end +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000000..c41dba5056 --- /dev/null +++ b/config.ru @@ -0,0 +1,3 @@ +# file: config.ru +require './app' +run Application diff --git a/lib/database_connection.rb b/lib/database_connection.rb new file mode 100644 index 0000000000..578f57a925 --- /dev/null +++ b/lib/database_connection.rb @@ -0,0 +1,38 @@ +# file: lib/database_connection.rb + +require 'pg' + +# This class is a thin "wrapper" around the +# PG library. We'll use it in our project to interact +# with the database using SQL. + +class DatabaseConnection + # This method connects to PostgreSQL using the + # PG gem. We connect to 127.0.0.1, and select + # the database name given in argument. + def self.connection + if ENV['DATABASE_URL'] != nil + @connection = PG.connect(ENV['DATABASE_URL']) + return + end + + if ENV['ENV'] == 'test' + database_name = 'chitter_challenge_test' + else + database_name = 'chitter_challenge' + end + @connection = PG.connect({ host: '127.0.0.1', dbname: database_name }) + end + + # This method executes an SQL query + # on the database, providing some optional parameters + # (you will learn a bit later about when to provide these parameters). + def self.exec_params(query, params) + if @connection.nil? + raise 'DatabaseConnection.exec_params: Cannot run a SQL query as the connection to'\ + 'the database was never opened. Did you make sure to call first the method '\ + '`DatabaseConnection.connect` in your app.rb file (or in your tests spec_helper.rb)?' + end + @connection.exec_params(query, params) + end +end diff --git a/lib/peep.rb b/lib/peep.rb new file mode 100644 index 0000000000..fb08566584 --- /dev/null +++ b/lib/peep.rb @@ -0,0 +1,3 @@ +class Peep + attr_accessor :id, :time, :content, :user_id +end diff --git a/lib/peep_repository.rb b/lib/peep_repository.rb new file mode 100644 index 0000000000..81d2d04a6d --- /dev/null +++ b/lib/peep_repository.rb @@ -0,0 +1,5 @@ +require_relative 'peep' + +class PeepRepository + +end diff --git a/lib/user.rb b/lib/user.rb new file mode 100644 index 0000000000..9b8f2a11fb --- /dev/null +++ b/lib/user.rb @@ -0,0 +1,3 @@ +class User + attr_accessor :id, :name, :username, :email, :password +end diff --git a/lib/user_repository.rb b/lib/user_repository.rb new file mode 100644 index 0000000000..28a33c301a --- /dev/null +++ b/lib/user_repository.rb @@ -0,0 +1,5 @@ +require_relative 'user' + +class UserRepository + +end diff --git a/spec/app_spec.rb b/spec/app_spec.rb new file mode 100644 index 0000000000..c19a400d02 --- /dev/null +++ b/spec/app_spec.rb @@ -0,0 +1,27 @@ +require "spec_helper" +require "rack/test" +require_relative "../../app" + +describe Application do + include Rack::Test::Methods + + let(:app) { Application.new } + + def reset_users_table + seed_sql = File.read('spec/seeds/users_seeds.sql') + connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) + connection.exec(seed_sql) + end + + def reset_peeps_table + seed_sql = File.read('spec/seeds/peeps_seeds.sql') + connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) + connection.exec(seed_sql) + end + + before(:each) do + reset_users_table + reset_peeps_table + end + +end diff --git a/spec/peep_repository_spec.rb b/spec/peep_repository_spec.rb new file mode 100644 index 0000000000..667982fd6d --- /dev/null +++ b/spec/peep_repository_spec.rb @@ -0,0 +1,14 @@ +require 'peep' +require 'peep_repository' + +def reset_peeps_table + seed_sql = File.read('spec/seeds/peeps_seeds.sql') + connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) + connection.exec(seed_sql) +end + +describe PeepRepository do + before(:each) do + reset_peeps_table + end +end diff --git a/spec/seeds/peeps_seeds.sql b/spec/seeds/peeps_seeds.sql new file mode 100644 index 0000000000..3c8e66af20 --- /dev/null +++ b/spec/seeds/peeps_seeds.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS peeps; + +CREATE TABLE peeps ( + id SERIAL PRIMARY KEY, + time TIMESTAMP, + content text, + user_id int, + constraint fk_user foreign key(user_id) + references users(id) + on delete cascade +); + +TRUNCATE TABLE peeps RESTART IDENTITY; + +INSERT INTO peeps ("time", "content", "user_id") VALUES +('2023-03-20 12:22:00', 'This is my first peep!', '1'), +('2023-04-01 10:19:00', 'Hello Chitter.', '2'); diff --git a/spec/seeds/users_seeds.sql b/spec/seeds/users_seeds.sql new file mode 100644 index 0000000000..f7ecaed8bc --- /dev/null +++ b/spec/seeds/users_seeds.sql @@ -0,0 +1,15 @@ +DROP TABLE IF EXISTS users; + +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + name text, + username text, + email text, + password text +); + +TRUNCATE TABLE users RESTART IDENTITY; + +INSERT INTO users ("name", "username", "email", "password") VALUES +('Alice Smith', 'malice12', 'alice.smith@gmail.com', 'password'), +('Bobby Blake', 'mrbobby', 'mrbobby@gmail.com', 'secret'); diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 252747d899..d5d9b36eff 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -15,3 +15,111 @@ puts "\e[33mTry it now! Just run: rubocop\e[0m" end end + +require 'database_connection' + +ENV['ENV'] = 'test' + +DatabaseConnection.connect + +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration + +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + config.disable_monkey_patching! + + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + config.warnings = true + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end diff --git a/spec/user_repository_spec.rb b/spec/user_repository_spec.rb new file mode 100644 index 0000000000..1410d72c78 --- /dev/null +++ b/spec/user_repository_spec.rb @@ -0,0 +1,14 @@ +require 'user' +require 'user_repository' + +def reset_users_table + seed_sql = File.read('spec/seeds/users_seeds.sql') + connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) + connection.exec(seed_sql) +end + +describe UserRepository do + before(:each) do + reset_users_table + end +end diff --git a/views/index.erb b/views/index.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/views/login.erb b/views/login.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/views/logout.erb b/views/logout.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/views/new_peep.erb b/views/new_peep.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/views/signup.erb b/views/signup.erb new file mode 100644 index 0000000000..e69de29bb2 From 80a1d5f27875907a45d31384a6663d6ecc5102cb Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 20:04:01 +0100 Subject: [PATCH 02/20] added bcrypt and sessions setup --- app.rb | 1 + lib/database_connection.rb | 2 +- lib/user_repository.rb | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app.rb b/app.rb index 52e69e9099..d6653b03f1 100644 --- a/app.rb +++ b/app.rb @@ -7,6 +7,7 @@ DatabaseConnection.connect class Application < Sinatra::Base + enable :sessions # This allows the app code to refresh # without having to restart the server. configure :development do diff --git a/lib/database_connection.rb b/lib/database_connection.rb index 578f57a925..2437cf16a3 100644 --- a/lib/database_connection.rb +++ b/lib/database_connection.rb @@ -10,7 +10,7 @@ class DatabaseConnection # This method connects to PostgreSQL using the # PG gem. We connect to 127.0.0.1, and select # the database name given in argument. - def self.connection + def self.connect(database_name) if ENV['DATABASE_URL'] != nil @connection = PG.connect(ENV['DATABASE_URL']) return diff --git a/lib/user_repository.rb b/lib/user_repository.rb index 28a33c301a..80494688ac 100644 --- a/lib/user_repository.rb +++ b/lib/user_repository.rb @@ -1,5 +1,6 @@ require_relative 'user' +require 'bcrypt' class UserRepository - + end From ad6d4068e0d07f49c626dd696b2c04f285e251f9 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 21:11:00 +0100 Subject: [PATCH 03/20] html skeleton and route plan --- route_plan.md | 161 +++++++++++++++++++++++++++++++++++ spec/user_repository_spec.rb | 2 + views/index.erb | 15 ++++ views/login.erb | 18 ++++ views/login_success.erb | 13 +++ views/logout.erb | 13 +++ views/new_peep.erb | 16 ++++ views/new_peep_success.erb | 13 +++ views/signup.erb | 22 +++++ views/signup_success.erb | 13 +++ 10 files changed, 286 insertions(+) create mode 100644 route_plan.md create mode 100644 views/login_success.erb create mode 100644 views/new_peep_success.erb create mode 100644 views/signup_success.erb diff --git a/route_plan.md b/route_plan.md new file mode 100644 index 0000000000..a29072b03f --- /dev/null +++ b/route_plan.md @@ -0,0 +1,161 @@ +# {{ METHOD }} {{ PATH}} Route Design Recipe + +_Copy this design recipe template to test-drive a Sinatra route._ + +## 1. Design the Route Signature + +Page: homepage +Request: GET / +No parameters +Response (200 OK) +index view with list of peeps, login status, link to log in/out, links to sign up and create peep + +Page: create new peep +Request: GET /peeps/new +No parameters +Response (200 OK) +new_peep view with form to create new peep + +Page: new peep created +Request: POST /peeps +Parameters: name, username, time, content +Response (200 OK) +new_peep_success view with link to homepage + +Page: signup +Request: GET /signup +No parameters +Response (200 OK) +signup view with form to create a new user + +Page: signup successful +Request: POST /signup +Parameters: name, email, username, password +Response (200 OK) +signup success view with link to login + +Page: log in +Request: GET /login +No parameters +Response (200 OK) +login view with form to log in + +Page: log in successful +Request: POST /login +Parameters: email, password +Response (200 OK) +login success view with link to homepage + +Page: log out +Request: GET /logout +No parameters +Response (200 OK) +logout view with button to log out + +Page: log out successful +Request: POST /logout +Parameters: user_id? +Response (200 OK) +Redirect to homepage + +You'll need to include: + * the HTTP method + * the path + * any query parameters (passed in the URL) + * or body parameters (passed in the request body) + +## 2. Design the Response + +The route might return different responses, depending on the result. + +For example, a route for a specific blog post (by its ID) might return `200 OK` if the post exists, but `404 Not Found` if the post is not found in the database. + +Your response might return plain text, JSON, or HTML code. + +_Replace the below with your own design. Think of all the different possible responses your route will return._ + +```html + + + + + + +

Post title

+
Post content
+ + +``` + +```html + + + + + + +

Sorry!

+
We couldn't find this post. Have a look at the homepage?
+ + +``` + +## 3. Write Examples + +_Replace these with your own design._ + +``` +# Request: + +GET /posts?id=1 + +# Expected response: + +Response for 200 OK +``` + +``` +# Request: + +GET /posts?id=276278 + +# Expected response: + +Response for 404 Not Found +``` + +## 4. Encode as Tests Examples + +```ruby +# EXAMPLE +# file: spec/integration/application_spec.rb + +require "spec_helper" + +describe Application do + include Rack::Test::Methods + + let(:app) { Application.new } + + context "GET /" do + it 'returns 200 OK' do + # Assuming the post with id 1 exists. + response = get('/posts?id=1') + + expect(response.status).to eq(200) + # expect(response.body).to eq(expected_response) + end + + it 'returns 404 Not Found' do + response = get('/posts?id=276278') + + expect(response.status).to eq(404) + # expect(response.body).to eq(expected_response) + end + end +end +``` + +## 5. Implement the Route + +Write the route and web server code to implement the route behaviour. diff --git a/spec/user_repository_spec.rb b/spec/user_repository_spec.rb index 1410d72c78..6dc8bdb2f9 100644 --- a/spec/user_repository_spec.rb +++ b/spec/user_repository_spec.rb @@ -11,4 +11,6 @@ def reset_users_table before(:each) do reset_users_table end + + end diff --git a/views/index.erb b/views/index.erb index e69de29bb2..90dc4e4cca 100644 --- a/views/index.erb +++ b/views/index.erb @@ -0,0 +1,15 @@ + + + + + Chitter Homepage + + +

+ Create a Peep + Sign up + Log in + Log out +

+ + diff --git a/views/login.erb b/views/login.erb index e69de29bb2..bdc4d2b643 100644 --- a/views/login.erb +++ b/views/login.erb @@ -0,0 +1,18 @@ + + + + + Log in + + +

Log in

+
+ + + + + + +
+ + diff --git a/views/login_success.erb b/views/login_success.erb new file mode 100644 index 0000000000..18f0a7e547 --- /dev/null +++ b/views/login_success.erb @@ -0,0 +1,13 @@ + + + + + Log in successful + + +

Log in successful!

+

+ Go back to the homepage. +

+ + diff --git a/views/logout.erb b/views/logout.erb index e69de29bb2..8d8b9c3b5e 100644 --- a/views/logout.erb +++ b/views/logout.erb @@ -0,0 +1,13 @@ + + + + + Log out + + +

Log out

+

+ +

+ + diff --git a/views/new_peep.erb b/views/new_peep.erb index e69de29bb2..50e418c1ec 100644 --- a/views/new_peep.erb +++ b/views/new_peep.erb @@ -0,0 +1,16 @@ + + + + + Create a new Peep + + +

Create a new Peep

+
+ + + + +
+ + diff --git a/views/new_peep_success.erb b/views/new_peep_success.erb new file mode 100644 index 0000000000..8acc3ab096 --- /dev/null +++ b/views/new_peep_success.erb @@ -0,0 +1,13 @@ + + + + + New Peep created + + +

+ New Peep created! + Go back to the homepage. +

+ + diff --git a/views/signup.erb b/views/signup.erb index e69de29bb2..03e00d69b7 100644 --- a/views/signup.erb +++ b/views/signup.erb @@ -0,0 +1,22 @@ + + + + + Sign up + + +

Sign up

+
+ + + + + + + + + + +
+ + diff --git a/views/signup_success.erb b/views/signup_success.erb new file mode 100644 index 0000000000..18a546c6a6 --- /dev/null +++ b/views/signup_success.erb @@ -0,0 +1,13 @@ + + + + + Sign up successful + + +

+ Sign up successful! + Go back to the homepage. +

+ + From a86623a48fe1b1048f0dc807f31615d87568253d Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 21:28:28 +0100 Subject: [PATCH 04/20] bcrypt gem installation fixed, database connect method fixed, peep repo all method tested --- Gemfile | 2 ++ Gemfile.lock | 2 ++ lib/database_connection.rb | 2 +- lib/peep_repository.rb | 19 ++++++++++++++++++- spec/app_spec.rb | 2 +- spec/peep_repository_spec.rb | 10 ++++++++++ 6 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 74fa8fecab..fdac52c66f 100644 --- a/Gemfile +++ b/Gemfile @@ -18,3 +18,5 @@ gem "webrick", "~> 1.8" gem "rack-test", "~> 2.1" gem "pg", "~> 1.4" + +gem "bcrypt" diff --git a/Gemfile.lock b/Gemfile.lock index a19258200f..f0a10ac592 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,6 +3,7 @@ GEM specs: ansi (1.5.0) ast (2.4.2) + bcrypt (3.1.18) diff-lcs (1.4.4) docile (1.4.0) multi_json (1.15.0) @@ -77,6 +78,7 @@ PLATFORMS ruby DEPENDENCIES + bcrypt pg (~> 1.4) rack-test (~> 2.1) rspec diff --git a/lib/database_connection.rb b/lib/database_connection.rb index 2437cf16a3..f7cc49dd3e 100644 --- a/lib/database_connection.rb +++ b/lib/database_connection.rb @@ -10,7 +10,7 @@ class DatabaseConnection # This method connects to PostgreSQL using the # PG gem. We connect to 127.0.0.1, and select # the database name given in argument. - def self.connect(database_name) + def self.connect if ENV['DATABASE_URL'] != nil @connection = PG.connect(ENV['DATABASE_URL']) return diff --git a/lib/peep_repository.rb b/lib/peep_repository.rb index 81d2d04a6d..253bdb0499 100644 --- a/lib/peep_repository.rb +++ b/lib/peep_repository.rb @@ -1,5 +1,22 @@ require_relative 'peep' class PeepRepository - + def all + peeps = [] + + sql = 'SELECT id, time, content, user_id FROM peeps;' + result_set = DatabaseConnection.exec_params(sql, []) + + result_set.each do |record| + peep = Peep.new + peep.id = record['id'] + peep.time = record['time'] + peep.content = record['content'] + peep.user_id = record['user_id'] + + peeps << peep + end + + return peeps + end end diff --git a/spec/app_spec.rb b/spec/app_spec.rb index c19a400d02..ed37652fdb 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" require "rack/test" -require_relative "../../app" +require_relative "../app" describe Application do include Rack::Test::Methods diff --git a/spec/peep_repository_spec.rb b/spec/peep_repository_spec.rb index 667982fd6d..3e9536b293 100644 --- a/spec/peep_repository_spec.rb +++ b/spec/peep_repository_spec.rb @@ -11,4 +11,14 @@ def reset_peeps_table before(:each) do reset_peeps_table end + + it 'finds all peeps' do + repo = PeepRepository.new + peeps = repo.all + + expect(peeps.length).to eq 2 + expect(peeps.first.content).to eq "This is my first peep!" + expect(peeps.first.id).to eq '1' + expect(peeps.first.user_id).to eq '1' + end end From d3e320dc43f327d13a7e630673946f3927bc075a Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 21:35:27 +0100 Subject: [PATCH 05/20] peep repo create method tested --- lib/peep_repository.rb | 8 ++++++++ spec/peep_repository_spec.rb | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/peep_repository.rb b/lib/peep_repository.rb index 253bdb0499..742d072d03 100644 --- a/lib/peep_repository.rb +++ b/lib/peep_repository.rb @@ -19,4 +19,12 @@ def all return peeps end + + def create(peep) + sql = 'INSERT INTO peeps (time, content, user_id) VALUES ($1, $2, $3);' + params = [peep.time, peep.content, peep.user_id] + result_set = DatabaseConnection.exec_params(sql, params) + + return peep + end end diff --git a/spec/peep_repository_spec.rb b/spec/peep_repository_spec.rb index 3e9536b293..4af5d663a3 100644 --- a/spec/peep_repository_spec.rb +++ b/spec/peep_repository_spec.rb @@ -21,4 +21,22 @@ def reset_peeps_table expect(peeps.first.id).to eq '1' expect(peeps.first.user_id).to eq '1' end + + it 'creates a new peep' do + repo = PeepRepository.new + + new_peep = Peep.new + new_peep.time = '2023-01-01 15:30:00' + new_peep.content = 'Peeps are cool' + new_peep.user_id = '2' + repo.create(new_peep) + + peeps = repo.all + + expect(peeps.length).to eq 3 + expect(peeps.last.time).to eq '2023-01-01 15:30:00' + expect(peeps.last.content).to eq 'Peeps are cool' + expect(peeps.last.user_id).to eq '2' + expect(peeps.last.id).to eq '3' + end end From 99f3d2bf4ae02cb6e98fabaf407b832656763531 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 21:56:13 +0100 Subject: [PATCH 06/20] updated seeds structure to account for foreign key constraint --- lib/user_repository.rb | 5 +++++ spec/app_spec.rb | 13 +++---------- spec/peep_repository_spec.rb | 6 +++--- spec/seeds/chitter_seeds.sql | 9 +++++++++ spec/seeds/create_table_seeds.sql | 21 +++++++++++++++++++++ spec/seeds/users_seeds.sql | 15 --------------- spec/user_repository_spec.rb | 21 +++++++++++++++++---- 7 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 spec/seeds/chitter_seeds.sql create mode 100644 spec/seeds/create_table_seeds.sql delete mode 100644 spec/seeds/users_seeds.sql diff --git a/lib/user_repository.rb b/lib/user_repository.rb index 80494688ac..4567f97524 100644 --- a/lib/user_repository.rb +++ b/lib/user_repository.rb @@ -2,5 +2,10 @@ require 'bcrypt' class UserRepository + def create(new_user) + encrypted_password = BCrypt::Password.create(new_user.password) + sql = 'INSERT INTO users (name, username, email, password) VALUES ($1, $2, $3, $4);' + params = [new_user.name, new_user.username, new_user.email, encrypted_password] + end end diff --git a/spec/app_spec.rb b/spec/app_spec.rb index ed37652fdb..999bb4d3ef 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -7,21 +7,14 @@ let(:app) { Application.new } - def reset_users_table - seed_sql = File.read('spec/seeds/users_seeds.sql') - connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) - connection.exec(seed_sql) - end - - def reset_peeps_table - seed_sql = File.read('spec/seeds/peeps_seeds.sql') + def reset_tables + seed_sql = File.read('spec/seeds/chitter_seeds.sql') connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) connection.exec(seed_sql) end before(:each) do - reset_users_table - reset_peeps_table + reset_tables end end diff --git a/spec/peep_repository_spec.rb b/spec/peep_repository_spec.rb index 4af5d663a3..d6707e98ea 100644 --- a/spec/peep_repository_spec.rb +++ b/spec/peep_repository_spec.rb @@ -1,15 +1,15 @@ require 'peep' require 'peep_repository' -def reset_peeps_table - seed_sql = File.read('spec/seeds/peeps_seeds.sql') +def reset_tables + seed_sql = File.read('spec/seeds/chitter_seeds.sql') connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) connection.exec(seed_sql) end describe PeepRepository do before(:each) do - reset_peeps_table + reset_tables end it 'finds all peeps' do diff --git a/spec/seeds/chitter_seeds.sql b/spec/seeds/chitter_seeds.sql new file mode 100644 index 0000000000..3ee5cb208a --- /dev/null +++ b/spec/seeds/chitter_seeds.sql @@ -0,0 +1,9 @@ +TRUNCATE TABLE users, peeps RESTART IDENTITY; + +INSERT INTO users ("name", "username", "email", "password") VALUES +('Alice Smith', 'malice12', 'alice.smith@gmail.com', 'password'), +('Bobby Blake', 'mrbobby', 'mrbobby@gmail.com', 'secret'); + +INSERT INTO peeps ("time", "content", "user_id") VALUES +('2023-03-20 12:22:00', 'This is my first peep!', '1'), +('2023-04-01 10:19:00', 'Hello Chitter.', '2'); diff --git a/spec/seeds/create_table_seeds.sql b/spec/seeds/create_table_seeds.sql new file mode 100644 index 0000000000..56d4ac8ade --- /dev/null +++ b/spec/seeds/create_table_seeds.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS users; + +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + name text, + username text, + email text, + password text +); + +DROP TABLE IF EXISTS peeps; + +CREATE TABLE peeps ( + id SERIAL PRIMARY KEY, + time TIMESTAMP, + content text, + user_id int, + constraint fk_user foreign key(user_id) + references users(id) + on delete cascade +); diff --git a/spec/seeds/users_seeds.sql b/spec/seeds/users_seeds.sql deleted file mode 100644 index f7ecaed8bc..0000000000 --- a/spec/seeds/users_seeds.sql +++ /dev/null @@ -1,15 +0,0 @@ -DROP TABLE IF EXISTS users; - -CREATE TABLE users ( - id SERIAL PRIMARY KEY, - name text, - username text, - email text, - password text -); - -TRUNCATE TABLE users RESTART IDENTITY; - -INSERT INTO users ("name", "username", "email", "password") VALUES -('Alice Smith', 'malice12', 'alice.smith@gmail.com', 'password'), -('Bobby Blake', 'mrbobby', 'mrbobby@gmail.com', 'secret'); diff --git a/spec/user_repository_spec.rb b/spec/user_repository_spec.rb index 6dc8bdb2f9..ae0c8d2e6c 100644 --- a/spec/user_repository_spec.rb +++ b/spec/user_repository_spec.rb @@ -1,16 +1,29 @@ require 'user' require 'user_repository' -def reset_users_table - seed_sql = File.read('spec/seeds/users_seeds.sql') +def reset_tables + seed_sql = File.read('spec/seeds/chitter_seeds.sql') connection = PG.connect({ host: '127.0.0.1', dbname: 'chitter_challenge_test' }) connection.exec(seed_sql) end describe UserRepository do before(:each) do - reset_users_table + reset_tables end - + it 'creates a new user' do + repo = UserRepository.new + + new_user = User.new + new_user.name = "Chewbacca" + new_user.username = "chewie123" + new_user.email = "chewie123@gmail.com" + new_user.password = "lightsaber" + user = repo.create(new_user) + + expect(user.name).to eq "Chewbacca" + expect(user.username).to eq "chewie123" + expect(user.email).to eq "chewie123@gmail.com" + end end From e8ee635e497804195d34cb73f44af45591d9fe83 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 21:58:51 +0100 Subject: [PATCH 07/20] user repo create method tested --- spec/seeds/peeps_seeds.sql | 17 ----------------- spec/user_repository_spec.rb | 6 +++--- 2 files changed, 3 insertions(+), 20 deletions(-) delete mode 100644 spec/seeds/peeps_seeds.sql diff --git a/spec/seeds/peeps_seeds.sql b/spec/seeds/peeps_seeds.sql deleted file mode 100644 index 3c8e66af20..0000000000 --- a/spec/seeds/peeps_seeds.sql +++ /dev/null @@ -1,17 +0,0 @@ -DROP TABLE IF EXISTS peeps; - -CREATE TABLE peeps ( - id SERIAL PRIMARY KEY, - time TIMESTAMP, - content text, - user_id int, - constraint fk_user foreign key(user_id) - references users(id) - on delete cascade -); - -TRUNCATE TABLE peeps RESTART IDENTITY; - -INSERT INTO peeps ("time", "content", "user_id") VALUES -('2023-03-20 12:22:00', 'This is my first peep!', '1'), -('2023-04-01 10:19:00', 'Hello Chitter.', '2'); diff --git a/spec/user_repository_spec.rb b/spec/user_repository_spec.rb index ae0c8d2e6c..76613a94ae 100644 --- a/spec/user_repository_spec.rb +++ b/spec/user_repository_spec.rb @@ -22,8 +22,8 @@ def reset_tables new_user.password = "lightsaber" user = repo.create(new_user) - expect(user.name).to eq "Chewbacca" - expect(user.username).to eq "chewie123" - expect(user.email).to eq "chewie123@gmail.com" + expect(user[0]).to eq "Chewbacca" + expect(user[1]).to eq "chewie123" + expect(user[2]).to eq "chewie123@gmail.com" end end From 74c0705e9aa9a9dad3c84b8c5128423bc380a61d Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 22:10:16 +0100 Subject: [PATCH 08/20] rewritten user repo create test --- lib/user_repository.rb | 17 +++++++++++++++++ spec/user_repository_spec.rb | 6 +++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/user_repository.rb b/lib/user_repository.rb index 4567f97524..8043f6fad7 100644 --- a/lib/user_repository.rb +++ b/lib/user_repository.rb @@ -7,5 +7,22 @@ def create(new_user) sql = 'INSERT INTO users (name, username, email, password) VALUES ($1, $2, $3, $4);' params = [new_user.name, new_user.username, new_user.email, encrypted_password] + DatabaseConnection.exec_params(sql, params) + + return new_user + end + + def find_by_email(email) + sql = 'SELECT id, name, username, email, password FROM users WHERE email = $1;' + result_set = DatabaseConnection.exec_params(sql, [email]) + + user = User.new + user.id = result_set[0]['id'] + user.name = result_set[0]['name'] + user.username = result_set[0]['username'] + user.email = result_set[0]['email'] + user.password = result_set[0]['password'] + + return user end end diff --git a/spec/user_repository_spec.rb b/spec/user_repository_spec.rb index 76613a94ae..ae0c8d2e6c 100644 --- a/spec/user_repository_spec.rb +++ b/spec/user_repository_spec.rb @@ -22,8 +22,8 @@ def reset_tables new_user.password = "lightsaber" user = repo.create(new_user) - expect(user[0]).to eq "Chewbacca" - expect(user[1]).to eq "chewie123" - expect(user[2]).to eq "chewie123@gmail.com" + expect(user.name).to eq "Chewbacca" + expect(user.username).to eq "chewie123" + expect(user.email).to eq "chewie123@gmail.com" end end From 408a9fd9c8f36d41dfabac7f043b34d697edd79d Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 22:12:42 +0100 Subject: [PATCH 09/20] user repo find by email method tested --- spec/user_repository_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/spec/user_repository_spec.rb b/spec/user_repository_spec.rb index ae0c8d2e6c..f9891b36b0 100644 --- a/spec/user_repository_spec.rb +++ b/spec/user_repository_spec.rb @@ -26,4 +26,13 @@ def reset_tables expect(user.username).to eq "chewie123" expect(user.email).to eq "chewie123@gmail.com" end + + it 'finds a user by email' do + repo = UserRepository.new + user = repo.find_by_email('alice.smith@gmail.com') + + expect(user.id).to eq '1' + expect(user.name).to eq 'Alice Smith' + expect(user.username).to eq 'malice12' + end end From cde34404cc09fe64b4259d57d709dc3a7fa293d2 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 22:56:50 +0100 Subject: [PATCH 10/20] user repo find by id method tested --- app.rb | 12 ++++++++++++ lib/peep_repository.rb | 2 +- lib/user_repository.rb | 14 ++++++++++++++ route_plan.md | 8 ++++---- spec/app_spec.rb | 8 ++++++++ spec/peep_repository_spec.rb | 8 ++++---- spec/user_repository_spec.rb | 9 +++++++++ views/index.erb | 8 ++++++++ 8 files changed, 60 insertions(+), 9 deletions(-) diff --git a/app.rb b/app.rb index d6653b03f1..8e1aaecc36 100644 --- a/app.rb +++ b/app.rb @@ -15,4 +15,16 @@ class Application < Sinatra::Base also_reload 'lib/user_repository' also_reload 'lib/peep_repository' end + + get '/' do + peep_repo = PeepRepository.new + peeps = peep_repo.all + + + peeps.each do |peep| + + end + + return erb(:index) + end end diff --git a/lib/peep_repository.rb b/lib/peep_repository.rb index 742d072d03..9a538d250f 100644 --- a/lib/peep_repository.rb +++ b/lib/peep_repository.rb @@ -4,7 +4,7 @@ class PeepRepository def all peeps = [] - sql = 'SELECT id, time, content, user_id FROM peeps;' + sql = 'SELECT id, time, content, user_id FROM peeps ORDER BY time DESC;' result_set = DatabaseConnection.exec_params(sql, []) result_set.each do |record| diff --git a/lib/user_repository.rb b/lib/user_repository.rb index 8043f6fad7..bf291fe712 100644 --- a/lib/user_repository.rb +++ b/lib/user_repository.rb @@ -25,4 +25,18 @@ def find_by_email(email) return user end + + def find(id) + sql = 'SELECT id, name, username, email, password FROM users WHERE id = $1;' + result_set = DatabaseConnection.exec_params(sql, [id]) + + user = User.new + user.id = result_set[0]['id'] + user.name = result_set[0]['name'] + user.username = result_set[0]['username'] + user.email = result_set[0]['email'] + user.password = result_set[0]['password'] + + return user + end end diff --git a/route_plan.md b/route_plan.md index a29072b03f..738ad72d74 100644 --- a/route_plan.md +++ b/route_plan.md @@ -5,7 +5,7 @@ _Copy this design recipe template to test-drive a Sinatra route._ ## 1. Design the Route Signature Page: homepage -Request: GET / +Request: GET / (peep_repo.all) No parameters Response (200 OK) index view with list of peeps, login status, link to log in/out, links to sign up and create peep @@ -16,7 +16,7 @@ No parameters Response (200 OK) new_peep view with form to create new peep -Page: new peep created +Page: new peep created (peep_repo.create(new_peep)) Request: POST /peeps Parameters: name, username, time, content Response (200 OK) @@ -28,7 +28,7 @@ No parameters Response (200 OK) signup view with form to create a new user -Page: signup successful +Page: signup successful (user_repo.create(new_user)) Request: POST /signup Parameters: name, email, username, password Response (200 OK) @@ -40,7 +40,7 @@ No parameters Response (200 OK) login view with form to log in -Page: log in successful +Page: log in successful (user_repo.find_by_email(email)) Request: POST /login Parameters: email, password Response (200 OK) diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 999bb4d3ef..1f9bb73391 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -17,4 +17,12 @@ def reset_tables reset_tables end + context "GET /" do + it "displays a list of all peeps in reverse chronological order" do + response = get("/") + expect(response.status).to eq 200 + expect(response.body).to include 'Content: This is my first peep!' + end + end + end diff --git a/spec/peep_repository_spec.rb b/spec/peep_repository_spec.rb index d6707e98ea..37394ebb38 100644 --- a/spec/peep_repository_spec.rb +++ b/spec/peep_repository_spec.rb @@ -12,14 +12,14 @@ def reset_tables reset_tables end - it 'finds all peeps' do + it 'finds all peeps in reverse chronological order' do repo = PeepRepository.new peeps = repo.all expect(peeps.length).to eq 2 - expect(peeps.first.content).to eq "This is my first peep!" - expect(peeps.first.id).to eq '1' - expect(peeps.first.user_id).to eq '1' + expect(peeps.first.content).to eq "Hello Chitter." + expect(peeps.first.id).to eq '2' + expect(peeps.first.user_id).to eq '2' end it 'creates a new peep' do diff --git a/spec/user_repository_spec.rb b/spec/user_repository_spec.rb index f9891b36b0..1f9830f9b1 100644 --- a/spec/user_repository_spec.rb +++ b/spec/user_repository_spec.rb @@ -35,4 +35,13 @@ def reset_tables expect(user.name).to eq 'Alice Smith' expect(user.username).to eq 'malice12' end + + it 'finds a user by id' do + repo = UserRepository.new + user = repo.find('1') + + expect(user.id).to eq '1' + expect(user.name).to eq 'Alice Smith' + expect(user.username).to eq 'malice12' + end end diff --git a/views/index.erb b/views/index.erb index 90dc4e4cca..a5b8f8382b 100644 --- a/views/index.erb +++ b/views/index.erb @@ -5,6 +5,14 @@ Chitter Homepage +

Chitter Homepage

+ <% @peeps.each do |peep| %> +
+ Content: <%= peep.content %>
+ Time posted: <%= peep.time %> +

+ <% end %> +

Create a Peep Sign up From 6713560b72312224b9c0bc92637917cf1bce714d Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 23:10:15 +0100 Subject: [PATCH 11/20] get / route tested --- app.rb | 6 +++++- spec/app_spec.rb | 1 + views/index.erb | 8 +++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app.rb b/app.rb index 8e1aaecc36..eb1e852b3c 100644 --- a/app.rb +++ b/app.rb @@ -17,12 +17,16 @@ class Application < Sinatra::Base end get '/' do + user_repo = UserRepository.new peep_repo = PeepRepository.new peeps = peep_repo.all + @complete_peep_info = [] peeps.each do |peep| - + user = user_repo.find(peep.user_id) + peep_info = {peep: peep, name: user.name, username: user.username} + @complete_peep_info << peep_info end return erb(:index) diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 1f9bb73391..e1a95120ba 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -22,6 +22,7 @@ def reset_tables response = get("/") expect(response.status).to eq 200 expect(response.body).to include 'Content: This is my first peep!' + expect(response.body).to include 'Username: @mrbobby' end end diff --git a/views/index.erb b/views/index.erb index a5b8f8382b..e40c99c9e3 100644 --- a/views/index.erb +++ b/views/index.erb @@ -6,10 +6,12 @@

Chitter Homepage

- <% @peeps.each do |peep| %> + <% @complete_peep_info.each do |peep_info| %>
- Content: <%= peep.content %>
- Time posted: <%= peep.time %> + Name: <%= peep_info[:name] %>
+ Username: @<%= peep_info[:username] %>
+ Content: <%= peep_info[:peep].content %>
+ Time posted: <%= peep_info[:peep].time %>

<% end %> From c595618c3f748a164054fc1cee8b9ae50e7db31f Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 23:17:50 +0100 Subject: [PATCH 12/20] get /signup route tested --- app.rb | 4 ++++ spec/app_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/app.rb b/app.rb index eb1e852b3c..af1aed72d4 100644 --- a/app.rb +++ b/app.rb @@ -31,4 +31,8 @@ class Application < Sinatra::Base return erb(:index) end + + get '/signup' do + return erb(:signup) + end end diff --git a/spec/app_spec.rb b/spec/app_spec.rb index e1a95120ba..0f1b1e69d7 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -26,4 +26,12 @@ def reset_tables end end + context "GET /signup" do + it "displays the signup page" do + response = get("/signup") + expect(response.status).to eq 200 + expect(response.body).to include '
' + end + end + end From 8f88a87d81c3d47fa1fc91e1400e1c4e5baed74d Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 23:26:53 +0100 Subject: [PATCH 13/20] post /signup route tested --- app.rb | 14 ++++++++++++++ spec/app_spec.rb | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/app.rb b/app.rb index af1aed72d4..14b6f7a899 100644 --- a/app.rb +++ b/app.rb @@ -35,4 +35,18 @@ class Application < Sinatra::Base get '/signup' do return erb(:signup) end + + post '/signup' do + repo = UserRepository.new + new_user = User.new + + new_user.name = params[:name] + new_user.username = params[:username] + new_user.email = params[:email] + new_user.password = params[:password] + + repo.create(new_user) + + return erb(:signup_success) + end end diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 0f1b1e69d7..68bfc8b335 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -34,4 +34,12 @@ def reset_tables end end + context "POST /signup" do + it "creates a new user in the database" do + response = post("/signup") + expect(response.status).to eq 200 + expect(response.body).to include 'Sign up successful!' + end + end + end From a6fb80e368288ece3d1cca4784214d4bf7ed785e Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Tue, 11 Apr 2023 23:29:18 +0100 Subject: [PATCH 14/20] get /login route tested --- app.rb | 4 ++++ spec/app_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/app.rb b/app.rb index 14b6f7a899..c9c3d5395d 100644 --- a/app.rb +++ b/app.rb @@ -32,6 +32,10 @@ class Application < Sinatra::Base return erb(:index) end + get '/login' do + return erb(:login) + end + get '/signup' do return erb(:signup) end diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 68bfc8b335..0ee52ceb30 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -26,6 +26,14 @@ def reset_tables end end + context "GET /login" do + it "displays the login page" do + response = get("/login") + expect(response.status).to eq 200 + expect(response.body).to include '

Log in

' + end + end + context "GET /signup" do it "displays the signup page" do response = get("/signup") From 45fe0b74361955ff9a38fce51a2de2eebdc64b61 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Wed, 12 Apr 2023 00:27:00 +0100 Subject: [PATCH 15/20] post /login route tested --- app.rb | 17 +++++++++++++++++ spec/app_spec.rb | 16 ++++++++++++++-- views/login_success.erb | 1 + views/wrong_password.erb | 13 +++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 views/wrong_password.erb diff --git a/app.rb b/app.rb index c9c3d5395d..944eb99164 100644 --- a/app.rb +++ b/app.rb @@ -3,6 +3,7 @@ require_relative 'lib/database_connection' require_relative 'lib/user_repository' require_relative 'lib/peep_repository' +require 'bcrypt' DatabaseConnection.connect @@ -36,6 +37,22 @@ class Application < Sinatra::Base return erb(:login) end + post '/login' do + email = params[:email] + password = params[:password] + + user_repo = UserRepository.new + + user = user_repo.find_by_email(email) + stored_password = BCrypt::Password.new(user.password) + + if stored_password == password + return erb(:login_success) + else + return erb(:wrong_password) + end + end + get '/signup' do return erb(:signup) end diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 0ee52ceb30..08c1062ce0 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -34,6 +34,18 @@ def reset_tables end end + context "POST /login" do + it "logs in the user with their credentials" do # seeded users weren't created with bcrypt so don't pass this test + response = post("/signup", name: 'Elton John', email: 'elton@john.com', username: 'rocketman', password: 'yellowbrickroad') + expect(response.status).to eq 200 + expect(response.body).to include 'Sign up successful!' + + response = post("/login", email: 'elton@john.com', password: 'yellowbrickroad') + expect(response.status).to eq 200 + expect(response.body).to include '

Log in successful!

' # add username to success page + end + end + context "GET /signup" do it "displays the signup page" do response = get("/signup") @@ -44,9 +56,9 @@ def reset_tables context "POST /signup" do it "creates a new user in the database" do - response = post("/signup") + response = post("/signup", name: 'Elton John', email: 'elton@john.com', username: 'rocketman', password: 'yellowbrickroad') expect(response.status).to eq 200 - expect(response.body).to include 'Sign up successful!' + expect(response.body).to include 'Sign up successful!' # add username to success page end end diff --git a/views/login_success.erb b/views/login_success.erb index 18f0a7e547..eb88c6cdcf 100644 --- a/views/login_success.erb +++ b/views/login_success.erb @@ -6,6 +6,7 @@

Log in successful!

+

Go back to the homepage.

diff --git a/views/wrong_password.erb b/views/wrong_password.erb new file mode 100644 index 0000000000..1a74cb2e0f --- /dev/null +++ b/views/wrong_password.erb @@ -0,0 +1,13 @@ + + + + + Wrong password. + + +

Wrong password.

+

+ Try logging in again. +

+ + From e70a324543053eb094a9a915b87b12f863696666 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Wed, 12 Apr 2023 00:29:57 +0100 Subject: [PATCH 16/20] POST /login wrong password route tested --- spec/app_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 08c1062ce0..b7c6499025 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -44,6 +44,16 @@ def reset_tables expect(response.status).to eq 200 expect(response.body).to include '

Log in successful!

' # add username to success page end + + it "tells the user they entered the wrong password" do + response = post("/signup", name: 'Elton John', email: 'elton@john.com', username: 'rocketman', password: 'yellowbrickroad') + expect(response.status).to eq 200 + expect(response.body).to include 'Sign up successful!' + + response = post("login", email: 'elton@john.com', password: 'stillstanding') + expect(response.status).to eq 200 + expect(response.body).to include 'Wrong password.' + end end context "GET /signup" do From 9b8f9bf81276a10ff206f3ebaa2e9210cede10c9 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Wed, 12 Apr 2023 00:36:14 +0100 Subject: [PATCH 17/20] get /peeps/new route tested --- app.rb | 6 ++++++ route_plan.md | 18 +++++++++--------- spec/app_spec.rb | 8 ++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/app.rb b/app.rb index 944eb99164..c7a88e462d 100644 --- a/app.rb +++ b/app.rb @@ -33,6 +33,10 @@ class Application < Sinatra::Base return erb(:index) end + get '/peeps/new' do + return erb(:new_peep) + end + get '/login' do return erb(:login) end @@ -70,4 +74,6 @@ class Application < Sinatra::Base return erb(:signup_success) end + + # add invalid_parameters? method end diff --git a/route_plan.md b/route_plan.md index 738ad72d74..72cdb2c42f 100644 --- a/route_plan.md +++ b/route_plan.md @@ -4,55 +4,55 @@ _Copy this design recipe template to test-drive a Sinatra route._ ## 1. Design the Route Signature -Page: homepage +[x] Page: homepage Request: GET / (peep_repo.all) No parameters Response (200 OK) index view with list of peeps, login status, link to log in/out, links to sign up and create peep -Page: create new peep +[ ] Page: create new peep Request: GET /peeps/new No parameters Response (200 OK) new_peep view with form to create new peep -Page: new peep created (peep_repo.create(new_peep)) +[ ] Page: new peep created (peep_repo.create(new_peep)) Request: POST /peeps Parameters: name, username, time, content Response (200 OK) new_peep_success view with link to homepage -Page: signup +[x] Page: signup Request: GET /signup No parameters Response (200 OK) signup view with form to create a new user -Page: signup successful (user_repo.create(new_user)) +[x] Page: signup successful (user_repo.create(new_user)) Request: POST /signup Parameters: name, email, username, password Response (200 OK) signup success view with link to login -Page: log in +[x] Page: log in Request: GET /login No parameters Response (200 OK) login view with form to log in -Page: log in successful (user_repo.find_by_email(email)) +[x] Page: log in successful (user_repo.find_by_email(email)) Request: POST /login Parameters: email, password Response (200 OK) login success view with link to homepage -Page: log out +[ ] Page: log out Request: GET /logout No parameters Response (200 OK) logout view with button to log out -Page: log out successful +[ ] Page: log out successful Request: POST /logout Parameters: user_id? Response (200 OK) diff --git a/spec/app_spec.rb b/spec/app_spec.rb index b7c6499025..953a73e0dc 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -26,6 +26,14 @@ def reset_tables end end + context "GET /peeps/new" do + it "displays the create new peep page" do + response = get("/peeps/new") + expect(response.status).to eq 200 + expect(response.body).to include '

Create a new Peep

' + end + end + context "GET /login" do it "displays the login page" do response = get("/login") From 03d58588f563e98675696a80ed3fefb36a9a86ff Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Wed, 12 Apr 2023 01:06:04 +0100 Subject: [PATCH 18/20] post /peeps route tested --- app.rb | 29 +++++++++++++++++++++++++---- route_plan.md | 2 +- spec/app_spec.rb | 26 ++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/app.rb b/app.rb index c7a88e462d..287d07a6b0 100644 --- a/app.rb +++ b/app.rb @@ -33,10 +33,6 @@ class Application < Sinatra::Base return erb(:index) end - get '/peeps/new' do - return erb(:new_peep) - end - get '/login' do return erb(:login) end @@ -51,12 +47,37 @@ class Application < Sinatra::Base stored_password = BCrypt::Password.new(user.password) if stored_password == password + session[:user_id] = user.id return erb(:login_success) else return erb(:wrong_password) end end + get '/peeps/new' do + if session[:user_id] == nil + return erb(:login) + else + return erb(:new_peep) + end + end + + post '/peeps' do + if session[:user_id] == nil + return erb(:login) + else + peep_repo = PeepRepository.new + new_peep = Peep.new + new_peep.time = Time.now + new_peep.content = params[:content] + new_peep.user_id = session[:user_id] + + peep_repo.create(new_peep) + + return erb(:new_peep_success) + end + end + get '/signup' do return erb(:signup) end diff --git a/route_plan.md b/route_plan.md index 72cdb2c42f..7c65c88f10 100644 --- a/route_plan.md +++ b/route_plan.md @@ -10,7 +10,7 @@ No parameters Response (200 OK) index view with list of peeps, login status, link to log in/out, links to sign up and create peep -[ ] Page: create new peep +[x] Page: create new peep Request: GET /peeps/new No parameters Response (200 OK) diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 953a73e0dc..669f76a57c 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -28,12 +28,38 @@ def reset_tables context "GET /peeps/new" do it "displays the create new peep page" do + # creates a user with a hashed password + response = post("/signup", name: 'Elton John', email: 'elton@john.com', username: 'rocketman', password: 'yellowbrickroad') + expect(response.status).to eq 200 + expect(response.body).to include 'Sign up successful!' + # logs that user in + response = post("/login", email: 'elton@john.com', password: 'yellowbrickroad') + expect(response.status).to eq 200 + expect(response.body).to include '

Log in successful!

' + # goes to the new peep page response = get("/peeps/new") expect(response.status).to eq 200 expect(response.body).to include '

Create a new Peep

' end end + context "POST /peeps" do + it "adds a new peep to the database" do + # creates a user with a hashed password + response = post("/signup", name: 'Elton John', email: 'elton@john.com', username: 'rocketman', password: 'yellowbrickroad') + expect(response.status).to eq 200 + expect(response.body).to include 'Sign up successful!' + # logs that user in + response = post("/login", email: 'elton@john.com', password: 'yellowbrickroad') + expect(response.status).to eq 200 + expect(response.body).to include '

Log in successful!

' + # creates a peep with that user + response = post("/peeps", time: '2023-04-12 11:11:00', content: 'Making Peeps', user_id: '3') + expect(response.status).to eq 200 + expect(response.body).to include 'New Peep created!' # add peep content to success page + end + end + context "GET /login" do it "displays the login page" do response = get("/login") From e3139be5fa07546393a5cc0ed9e19c0975ac24b4 Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Wed, 12 Apr 2023 01:12:21 +0100 Subject: [PATCH 19/20] update password input type in forms, update form submit button labels --- route_plan.md | 2 +- views/login.erb | 4 ++-- views/new_peep.erb | 2 +- views/signup.erb | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/route_plan.md b/route_plan.md index 7c65c88f10..6c642a0c78 100644 --- a/route_plan.md +++ b/route_plan.md @@ -16,7 +16,7 @@ No parameters Response (200 OK) new_peep view with form to create new peep -[ ] Page: new peep created (peep_repo.create(new_peep)) +[x] Page: new peep created (peep_repo.create(new_peep)) Request: POST /peeps Parameters: name, username, time, content Response (200 OK) diff --git a/views/login.erb b/views/login.erb index bdc4d2b643..3f4ec090c3 100644 --- a/views/login.erb +++ b/views/login.erb @@ -10,9 +10,9 @@ - + - + diff --git a/views/new_peep.erb b/views/new_peep.erb index 50e418c1ec..a620f3fb48 100644 --- a/views/new_peep.erb +++ b/views/new_peep.erb @@ -10,7 +10,7 @@ - + diff --git a/views/signup.erb b/views/signup.erb index 03e00d69b7..6f369b96af 100644 --- a/views/signup.erb +++ b/views/signup.erb @@ -14,9 +14,9 @@ - + - + From 3ef3a5b06dbc6b3577ba50e6465ab611ff513b5e Mon Sep 17 00:00:00 2001 From: natashabuckham Date: Wed, 12 Apr 2023 10:20:55 +0100 Subject: [PATCH 20/20] added comments for future work --- app.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.rb b/app.rb index 287d07a6b0..26f603e97d 100644 --- a/app.rb +++ b/app.rb @@ -30,7 +30,7 @@ class Application < Sinatra::Base @complete_peep_info << peep_info end - return erb(:index) + return erb(:index) # add log in status logic end get '/login' do @@ -86,7 +86,7 @@ class Application < Sinatra::Base repo = UserRepository.new new_user = User.new - new_user.name = params[:name] + new_user.name = params[:name] # name and username must be unique new_user.username = params[:username] new_user.email = params[:email] new_user.password = params[:password]