Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ gem "thruster", require: false
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin Ajax possible
# gem "rack-cors"

# BCrypt for password hashing
gem "bcrypt", "~> 3.1"

group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
Expand All @@ -43,7 +46,8 @@ group :development, :test do
gem "brakeman", require: false

# Testing Framework
gem "minitest", "~> 6.0"
# Minitest 6.0+ is having some issues with how tests are currently written
gem "minitest", "~> 5.0"
gem "minitest-reporters"

# Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
Expand Down
7 changes: 4 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ GEM
ansi (1.5.0)
ast (2.4.3)
base64 (0.3.0)
bcrypt (3.1.21)
bcrypt_pbkdf (1.1.2)
bigdecimal (4.0.1)
bootsnap (1.20.1)
Expand Down Expand Up @@ -137,8 +138,7 @@ GEM
net-smtp
marcel (1.1.0)
mini_mime (1.1.5)
minitest (6.0.1)
prism (~> 1.5)
minitest (5.27.0)
minitest-reporters (1.7.1)
ansi
builder
Expand Down Expand Up @@ -323,11 +323,12 @@ PLATFORMS
x86_64-linux-musl

DEPENDENCIES
bcrypt (~> 3.1)
bootsnap
brakeman
debug
kamal
minitest (~> 6.0)
minitest (~> 5.0)
minitest-reporters
pg (~> 1.6)
puma (>= 5.0)
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.PHONY: up down logs build test run
up:
@docker-compose -f docker-compose.yml up -d
down:
Expand All @@ -6,5 +7,7 @@ logs:
@docker-compose -f docker-compose.yml logs -f
build:
@docker build --build-arg RAILS_MASTER_KEY=$(cat config/master.key) -f Dockerfile -t simplesave-api:latest .
test:
@rails test
run:
@rails s
@rails server
5 changes: 5 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class User < ApplicationRecord
has_secure_password

validates :email, presence: true, uniqueness: true
end
10 changes: 10 additions & 0 deletions db/migrate/20260108050125_create_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreateUsers < ActiveRecord::Migration[8.1]
def change
create_table :users do |t|
t.string :email, null: false, index: { unique: true }
t.string :password_digest, null: false

t.timestamps
end
end
end
9 changes: 8 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions test/fixtures/users.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

alice:
email: alice@example.com
password_digest: <%= BCrypt::Password.create(TestCredentials::DEFAULT_PASSWORD) %>

bob:
email: bob@example.com
password_digest: <%= BCrypt::Password.create(TestCredentials::DEFAULT_PASSWORD) %>
55 changes: 55 additions & 0 deletions test/models/user_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require "test_helper"

class UserTest < ActiveSupport::TestCase
test "is valid with email and password" do
user = User.new(
email: "newuser@example.com",
password: TestCredentials::DEFAULT_PASSWORD,
password_confirmation: TestCredentials::DEFAULT_PASSWORD
)

assert user.valid?
end

test "is invalid without email" do
user = User.new(
password: TestCredentials::DEFAULT_PASSWORD,
password_confirmation: TestCredentials::DEFAULT_PASSWORD
)

assert_not user.valid?
assert_includes user.errors[:email], "can't be blank"
end

test "is invalid without password" do
user = User.new(email: "nopassword@example.com")

assert_not user.valid?
assert_includes user.errors[:password], "can't be blank"
end

test "email must be unique" do
existing_user = users(:alice)

duplicate = User.new(
email: existing_user.email,
password: TestCredentials::DEFAULT_PASSWORD,
password_confirmation: TestCredentials::DEFAULT_PASSWORD
)

assert_not duplicate.valid?
assert_includes duplicate.errors[:email], "has already been taken"
end

test "authenticates with correct password" do
user = users(:alice)

assert user.authenticate(TestCredentials::DEFAULT_PASSWORD)
end

test "does not authenticate with incorrect password" do
user = users(:alice)

assert_not user.authenticate("wrong-password")
end
end
3 changes: 3 additions & 0 deletions test/support/auth_constants.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module TestCredentials
DEFAULT_PASSWORD = "password123"
end
5 changes: 5 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
require "minitest/reporters"
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new

require "bcrypt"

# Load support file:
Dir[Rails.root.join("test/support/**/*.rb")].each { |f| require f }

module ActiveSupport
class TestCase
# Run tests in parallel with specified workers
Expand Down