Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pablo Joyce chitter challenge #2174

Open
wants to merge 80 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
5ccef5b
chitter plan setup
pablisch Apr 6, 2023
9956e10
limited project setup
pablisch Apr 6, 2023
04ddf5e
Project files setup. Rackup error.
pablisch Apr 7, 2023
e4c30e0
app.rb not seeing peep methods. RSpec tests ok
pablisch Apr 7, 2023
a9307db
all tests pass. peep & user #s not seen by app.rb
pablisch Apr 7, 2023
fb90cd7
setup pages. peep/user #s working. tests pass
pablisch Apr 8, 2023
f9417d0
create peep part coded. Test passing
pablisch Apr 8, 2023
6a3a0e4
Added hidden input to add_peep.erb for user_id val
pablisch Apr 9, 2023
60390cf
Working again after anomalous errors
pablisch Apr 9, 2023
5821da3
basic register process working and tested
pablisch Apr 9, 2023
5f73b84
Part way through vaildation. tests passing.
pablisch Apr 10, 2023
3ff7f2b
pablisch Apr 10, 2023
964a449
Valdiation complete except unique
pablisch Apr 10, 2023
8eda5ca
unique email and username validation and tests
pablisch Apr 10, 2023
cca3382
installed bcrypt
pablisch Apr 10, 2023
4d53c3e
Added bcrypt code that has broken tests
pablisch Apr 10, 2023
1144a1a
Edited PWs in seeds tables to hashes. Tests good
pablisch Apr 10, 2023
2897786
reverse bcrypt. some css.
pablisch Apr 10, 2023
5f5a03e
Some small css and index.erb changes
pablisch Apr 11, 2023
0a2a574
Fixed issue of wrong db being used
pablisch Apr 11, 2023
fa32980
seeds edit and about to start bcrypt again
pablisch Apr 11, 2023
45dd4d3
bcrypt implemented and working
pablisch Apr 11, 2023
44653c7
Merge pull request #1 from pablisch/bcrypt
pablisch Apr 11, 2023
11fb2be
mostly css changes and erb page layout
pablisch Apr 11, 2023
7e3e7f6
Playing around with time format
pablisch Apr 11, 2023
8f77719
css almost done. tests passing
pablisch Apr 11, 2023
378b67a
updated tables
pablisch Apr 11, 2023
87684c9
setup for deploy
pablisch Apr 11, 2023
9ea5c6f
updated database_connect for Render
pablisch Apr 11, 2023
28e1758
commented out all uses of logged var
pablisch Apr 11, 2023
0047743
deploy unsuccessful. changes reversed.
pablisch Apr 11, 2023
c8da0b6
images moved
pablisch Apr 12, 2023
dd80942
shortened route paths. Tests all working
pablisch Apr 13, 2023
98178ce
edit logged to session user_id
pablisch Apr 13, 2023
195030b
commented out all instances of settings.logged
pablisch Apr 13, 2023
ad1e613
Database connection set to deploy
pablisch Apr 13, 2023
dbf2c85
remove p test from peep repo rb
pablisch Apr 13, 2023
6e16997
Removed all logged mentions from app.rb
pablisch Apr 13, 2023
316a1f1
Removed logged from add peep erb
pablisch Apr 13, 2023
cc3669b
Removed last 'logged' from index erb
pablisch Apr 13, 2023
54e41ec
indent changes in index.erb
pablisch Apr 13, 2023
0fd6fe2
conditional correction in index.rb
pablisch Apr 13, 2023
a45ff71
Removed settings.logged from register & login erb
pablisch Apr 13, 2023
77e969b
replaced Sinatra validation var for session var
pablisch Apr 13, 2023
251ad3d
Edit database connection for deploy
pablisch Apr 13, 2023
0cb10f7
Disposed of settings.message. The last Sinatra var
pablisch Apr 13, 2023
b64a3e9
css styling for buttons and input fields
pablisch Apr 13, 2023
4d5e967
Added padding to below error messages
pablisch Apr 13, 2023
2f4c3ce
extra padding for header elements
pablisch Apr 13, 2023
94a3411
15px padding below panel p
pablisch Apr 13, 2023
b9954d3
panel p margin 10px
pablisch Apr 13, 2023
53625b8
text box margins
pablisch Apr 14, 2023
da5e800
extra margin bottom for text boxes
pablisch Apr 14, 2023
8d7e703
margin left for text boxes
pablisch Apr 14, 2023
e2337b2
correct margin for new peep page
pablisch Apr 14, 2023
c69b125
adjustment to new peep page margins
pablisch Apr 14, 2023
ec5acbe
Added hover colour for nav links
pablisch Apr 14, 2023
4b4646f
button hover colour change
pablisch Apr 14, 2023
4a4c1be
nav h1 hover white
pablisch Apr 14, 2023
a58df1d
DB connection set for local view
pablisch Apr 14, 2023
5f57bdf
small css edits to nav
pablisch Apr 14, 2023
3586557
db connect to deploy
pablisch Apr 14, 2023
94a0c34
text input field alignment
pablisch Apr 14, 2023
853d26f
Comment out render deploy database connect code
pablisch Apr 19, 2023
73f3ef2
Fixed test and edits to README
pablisch Jun 23, 2023
cbe4f45
More README and chitter_plan updates
pablisch Jun 23, 2023
53e9a3f
Final, for now, README edit
pablisch Jun 23, 2023
3f71018
main README edit
pablisch Jun 23, 2023
b0e66c1
Merge branch 'main' into local-server
pablisch Jun 23, 2023
975a2d7
Merge pull request #2 from pablisch/local-server
pablisch Jun 23, 2023
6fde111
Added links and two images to readme
pablisch Jun 27, 2023
d054c50
Added images for test and coverage
pablisch Jun 27, 2023
8bad1fb
Format test
pablisch Jun 27, 2023
66ce8d4
Format test
pablisch Jun 27, 2023
b93f21f
Format test
pablisch Jun 27, 2023
948055e
Format test
pablisch Jun 27, 2023
755b40a
Format test
pablisch Jun 27, 2023
55f9ca9
Added tech symbols
pablisch Jun 27, 2023
212c657
Changed user emails and passwords
pablisch Jul 15, 2023
eb65387
Updated tables and seeds
pablisch Jul 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,14 @@ end
group :development, :test do
gem 'rubocop', '1.20'
end

gem "pg", "~> 1.4"

gem "sinatra", "~> 3.0"
gem "sinatra-contrib", "~> 3.0"
gem "webrick", "~> 1.8"
gem "rack-test", "~> 2.1"

gem "rackup", "~> 1.0"

gem "bcrypt", "~> 3.1"
37 changes: 37 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@ 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)
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.5)
rack
rack-test (2.1.0)
rack (>= 1.3)
rackup (1.0.0)
rack (< 3)
webrick
rainbow (3.0.0)
regexp_parser (2.1.1)
rexml (3.2.5)
Expand Down Expand Up @@ -36,6 +49,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)
Expand All @@ -46,18 +60,41 @@ GEM
terminal-table
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.3)
sinatra (3.0.5)
mustermann (~> 3.0)
rack (~> 2.2, >= 2.2.4)
rack-protection (= 3.0.5)
tilt (~> 2.0)
sinatra-contrib (3.0.5)
multi_json
mustermann (~> 3.0)
rack-protection (= 3.0.5)
sinatra (= 3.0.5)
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
x86_64-darwin-20
x86_64-darwin-21
x86_64-linux

DEPENDENCIES
bcrypt (~> 3.1)
pg (~> 1.4)
rack-test (~> 2.1)
rackup (~> 1.0)
rspec
rubocop (= 1.20)
simplecov
simplecov-console
sinatra (~> 3.0)
sinatra-contrib (~> 3.0)
webrick (~> 1.8)

RUBY VERSION
ruby 3.0.2p107
Expand Down
21 changes: 21 additions & 0 deletions README.md

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could include how to run the program

Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# Chitter Challenge by Pablo Joyce

This project uses:
* Ruby
* PostgreSQL
* ERB
* Rackup
* Sinatra
* Webrick
* Git
* GitHub
* Bcrypt

In development, I employed:
* Postman
* TablePlus
* RSpec




Chitter Challenge
=================

Expand Down
167 changes: 167 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
require_relative 'lib/database_connection'
require 'sinatra/base'
require 'sinatra/reloader'
require_relative 'lib/user_repository'
require_relative 'lib/peep_repository'
require 'bcrypt'

DatabaseConnection.connect

class Application < Sinatra::Base

enable :sessions # allows users sessions

# 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'
set :message, "Log in to create new peeps."
set :logged, false
set :validation_error, ""
end

get '/' do
repo = PeepRepository.new
peeps = repo.all_with_names
@peep_info = peeps.map{ |peep| [peep.username, peep.time, peep.body, peep.tags, peep.name]}.reverse
return erb(:index)
end

get '/peeps/new' do
@user_id = session[:user_id] # placeholder code for sending logged in user id!!!
return erb(:add_peep)
end

post '/peeps' do
@body, @tags, @user_id = params[:body], params[:tags],params[:user_id]
script_check([@body, @tags, @user_id], '/peeps/new')
validate_string(@body, "peep")
repo = PeepRepository.new
new_peep = Peep.new
new_peep.body = @body
new_peep.time = Time.now#.strftime("%Y-%m-%d %T")
new_peep.tags = @tags
new_peep.user_id = @user_id
repo.create(new_peep)
return redirect('/')
end

get '/register/new' do
return erb(:register)
end

post '/register' do
@name, @username, @email, @password = params[:name], params[:username], params[:email], params[:password]
script_check([@name, @username, @email, @password], '/register/new')
validate_string(@name, "name")
validate_string(@username, "username")
validate_email(@email)
username_email_unique(@username, @email)
validate_password(@password)
user_repo = UserRepository.new
new_user = User.new
new_user.name = @name
new_user.username = @username
new_user.email = @email
new_user.password = @password
user_repo.create(new_user)
user = user_repo.find_by_email(@email)
login_user(user)
return redirect('/')
end

get '/login/form' do
return erb(:login)
end

post '/login' do
@email = params[:email]
@password = params[:password]
script_check([@email, @password], '/login/form')
email_exists(@email)
user = UserRepository.new.find_by_email(@email)
email_password_match(user, @password)
return redirect('/')
end

get '/logout' do
session.clear
settings.logged = false
settings.message = "Log in to create new peeps."
return redirect('/')
end

helpers do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Could move the helpers functions into another file for readability!

def validate_string(name, field)
unless name.match?(/[a-zA-Z]/)
settings.validation_error = "Invalid #{field}: must contain one or more letters.\n"
return redirect('register/new')
end
end

def validate_email(email)
unless email =~ URI::MailTo::EMAIL_REGEXP
settings.validation_error = "Invalid email: please enter a valid email to register.\n"
return redirect('register/new')
end
end

def validate_password(password)
unless password.match(/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{8,}$/)
settings.validation_error = "Invalid password: minimum eight characters and contain at least one lowercase letter, uppercase letter and digit.\n"
return redirect('register/new')
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good concise validation methods

def username_email_unique(username, email)
if UserRepository.new.all_usernames.include?(username)
settings.validation_error = "That username is already taken.\n"
return redirect('register/new')
end
if UserRepository.new.all_emails.include?(email)
settings.validation_error = "That email is already registered to a user.\n"
return redirect('register/new')
end
end

def email_exists(email)
emails = UserRepository.new.all_emails
unless emails.include?(email)
settings.validation_error = "Email and password do not match any registered user.\n"
return redirect('login/form')
end
end

def email_password_match(user, entered_password)
stored_password = BCrypt::Password.new(user.password)
unless stored_password == entered_password # i.e. UNLESS <stored-password-hash> == <entered-password>
session[:user_id] = nil
settings.logged = false
settings.validation_error = "Email and password do not match any registered user.\n"
return redirect('/login/form')
end
login_user(user)
# session[:username] = user.username
# session[:user_id] = user.id
settings.logged = true
end

def login_user(user)
session[:username] = user.username
session[:user_id] = user.id
settings.logged = true
end

def script_check(inputs_array, redirect_path)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: use ERB::Util.html.escape to better escape user input

if inputs_array.join.match?(/[<>\/]/)
session[:user_id] = nil
settings.logged = false
settings.validation_error = "'<', '>' and '/' are not permitted characters.\n"
return redirect(redirect_path)
end
end

end
end
2 changes: 2 additions & 0 deletions config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require './app'
run Application
44 changes: 44 additions & 0 deletions lib/database_connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'pg'

class DatabaseConnection
# This method connects to PostgreSQL using the PG gem. We connect to 127.0.0.1

################## RENDER connect method
# def self.connect
# If the environment variable (set by Render)
# is present, use this to open the connection.
# if ENV['DATABASE_URL'] != nil
# @connection = PG.connect(ENV['DATABASE_URL'])
# return
# end

# if ENV['ENV'] == 'test'
# database_name = 'chitter_test'
# else
# database_name = 'chitter_render_db'
# end
# @connection = PG.connect({ host: '127.0.0.1', dbname: database_name })
# end




################### local connect method - NOT for RENDER
def self.connect
if ENV['ENV'] == 'test'
database_name = 'chitter_test'
else
database_name = 'chitter'
end
@connection = PG.connect({ host: '127.0.0.1', dbname: database_name })
end

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
7 changes: 7 additions & 0 deletions lib/peep.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Peep
attr_accessor :id, :body, :time, :tags, :user_id, :username, :name

# def initialize
# @tags = []
# end
end
54 changes: 54 additions & 0 deletions lib/peep_repository.rb

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Use an ORM to access the database instead!

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require_relative './peep'
require_relative './user'
require 'time'

class PeepRepository
def all # return all peeps
sql = 'SELECT * FROM peeps;'
results = DatabaseConnection.exec_params(sql, [])
peeps = []
results.each{ |record| peeps << peep_builder(record) }
return peeps
end

def all_with_names
sql = 'SELECT users.name, users.username, peeps.body, peeps.time, peeps.tags, peeps.user_id
FROM users
JOIN peeps
ON peeps.user_id = users.id;'
results = DatabaseConnection.exec_params(sql, [])
peeps_with_names = []
p results
results.each do |record|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a peep builder!

peep = Peep.new
peep.id = record['id'].to_i
peep.body = record['body']
peep.time = (record['time'])
peep.tags = record['tags']
peep.user_id = record['user_id'].to_i
peep.name = record['name']
peep.username = record['username']
peeps_with_names << peep
end
return peeps_with_names
end

def create(peep)
sql = 'INSERT INTO peeps (body, time, tags, user_id) VALUES ($1, $2, $3, $4);'
params = [peep.body, peep.time, peep.tags, peep.user_id]
DatabaseConnection.exec_params(sql, params)
end

private

def peep_builder(record) # used to build peeps in iteration by #all
peep = Peep.new
peep.id = record['id'].to_i
peep.body = record['body']
peep.time = record['time']
peep.tags = record['tags']
peep.user_id = record['user_id'].to_i
return peep
end
end

Loading