Compare commits

...
Sign in to create a new pull request.

11 commits

Author SHA1 Message Date
dependabot[bot]
e884747fde Bump bootsnap from 1.18.5 to 1.18.6
Bumps [bootsnap](https://github.com/Shopify/bootsnap) from 1.18.5 to 1.18.6.
- [Changelog](https://github.com/Shopify/bootsnap/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Shopify/bootsnap/compare/v1.18.5...v1.18.6)

---
updated-dependencies:
- dependency-name: bootsnap
  dependency-version: 1.18.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-20 15:27:21 +02:00
dependabot[bot]
3901d78b4c Bump kamal from 2.6.0 to 2.6.1
Bumps [kamal](https://github.com/basecamp/kamal) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/basecamp/kamal/releases)
- [Commits](https://github.com/basecamp/kamal/compare/v2.6.0...v2.6.1)

---
updated-dependencies:
- dependency-name: kamal
  dependency-version: 2.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-20 15:26:53 +02:00
8ee5dd9322 Add posts, tags, tagging, to database. Create references to align with new DB model. Add image of mermaid template model. 2025-05-15 16:40:54 +02:00
4edae5e7bb Configure tests and helpers for current backend state 2025-05-15 16:40:54 +02:00
471440804c Remove leftover note tests 2025-05-15 16:40:54 +02:00
372fe53947 Add session & user management in the backend 2025-05-15 16:40:54 +02:00
9aee9adfce Update gems & gitignore 2025-05-15 16:40:54 +02:00
982b72494c Add: image database table, image test site, image upload support 2025-05-15 16:40:54 +02:00
dependabot[bot]
73d63f92e4 Bump bootsnap from 1.18.4 to 1.18.5
Bumps [bootsnap](https://github.com/Shopify/bootsnap) from 1.18.4 to 1.18.5.
- [Changelog](https://github.com/Shopify/bootsnap/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Shopify/bootsnap/compare/v1.18.4...v1.18.5)

---
updated-dependencies:
- dependency-name: bootsnap
  dependency-version: 1.18.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-15 16:40:26 +02:00
dependabot[bot]
5f52213972 Bump kamal from 2.5.3 to 2.6.0
Bumps [kamal](https://github.com/basecamp/kamal) from 2.5.3 to 2.6.0.
- [Release notes](https://github.com/basecamp/kamal/releases)
- [Commits](https://github.com/basecamp/kamal/compare/v2.5.3...v2.6.0)

---
updated-dependencies:
- dependency-name: kamal
  dependency-version: 2.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-15 16:40:16 +02:00
dependabot[bot]
3d223b3b0d Bump solid_cable from 3.0.7 to 3.0.8
Bumps [solid_cable](https://github.com/rails/solid_cable) from 3.0.7 to 3.0.8.
- [Release notes](https://github.com/rails/solid_cable/releases)
- [Commits](https://github.com/rails/solid_cable/compare/v3.0.7...v3.0.8)

---
updated-dependencies:
- dependency-name: solid_cable
  dependency-version: 3.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-15 16:40:07 +02:00
47 changed files with 515 additions and 17 deletions

3
.gitignore vendored
View file

@ -32,3 +32,6 @@
# Ignore master key for decrypting credentials and more. # Ignore master key for decrypting credentials and more.
/config/master.key /config/master.key
# Ignore DS Store
*.DS_Store

View file

@ -18,7 +18,7 @@ gem "stimulus-rails"
gem "jbuilder" gem "jbuilder"
# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
# gem "bcrypt", "~> 3.1.7" gem "bcrypt", "~> 3.1.7"
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ windows jruby ] gem "tzinfo-data", platforms: %i[ windows jruby ]

View file

@ -76,11 +76,12 @@ GEM
public_suffix (>= 2.0.2, < 7.0) public_suffix (>= 2.0.2, < 7.0)
ast (2.4.3) ast (2.4.3)
base64 (0.2.0) base64 (0.2.0)
bcrypt (3.1.20)
bcrypt_pbkdf (1.1.1) bcrypt_pbkdf (1.1.1)
benchmark (0.4.0) benchmark (0.4.0)
bigdecimal (3.1.9) bigdecimal (3.1.9)
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.18.4) bootsnap (1.18.6)
msgpack (~> 1.2) msgpack (~> 1.2)
brakeman (7.0.2) brakeman (7.0.2)
racc racc
@ -127,13 +128,13 @@ GEM
actionview (>= 5.0.0) actionview (>= 5.0.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
json (2.11.3) json (2.11.3)
kamal (2.5.3) kamal (2.6.1)
activesupport (>= 7.0) activesupport (>= 7.0)
base64 (~> 0.2) base64 (~> 0.2)
bcrypt_pbkdf (~> 1.0) bcrypt_pbkdf (~> 1.0)
concurrent-ruby (~> 1.2) concurrent-ruby (~> 1.2)
dotenv (~> 3.1) dotenv (~> 3.1)
ed25519 (~> 1.2) ed25519 (~> 1.4)
net-ssh (~> 7.3) net-ssh (~> 7.3)
sshkit (>= 1.23.0, < 2.0) sshkit (>= 1.23.0, < 2.0)
thor (~> 1.3) thor (~> 1.3)
@ -141,7 +142,7 @@ GEM
language_server-protocol (3.17.0.4) language_server-protocol (3.17.0.4)
lint_roller (1.1.0) lint_roller (1.1.0)
logger (1.7.0) logger (1.7.0)
loofah (2.24.0) loofah (2.24.1)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.12.0) nokogiri (>= 1.12.0)
mail (2.8.1) mail (2.8.1)
@ -197,7 +198,7 @@ GEM
activesupport (>= 7.0.0) activesupport (>= 7.0.0)
rack rack
railties (>= 7.0.0) railties (>= 7.0.0)
psych (5.2.4) psych (5.2.6)
date date
stringio stringio
public_suffix (6.0.2) public_suffix (6.0.2)
@ -205,8 +206,8 @@ GEM
nio4r (~> 2.0) nio4r (~> 2.0)
raabro (1.4.0) raabro (1.4.0)
racc (1.8.1) racc (1.8.1)
rack (3.1.13) rack (3.1.14)
rack-session (2.1.0) rack-session (2.1.1)
base64 (>= 0.1.0) base64 (>= 0.1.0)
rack (>= 3.0.0) rack (>= 3.0.0)
rack-test (2.2.0) rack-test (2.2.0)
@ -287,7 +288,7 @@ GEM
rexml (~> 3.2, >= 3.2.5) rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0) rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0) websocket (~> 1.0)
solid_cable (3.0.7) solid_cable (3.0.8)
actioncable (>= 7.2) actioncable (>= 7.2)
activejob (>= 7.2) activejob (>= 7.2)
activerecord (>= 7.2) activerecord (>= 7.2)
@ -363,6 +364,7 @@ PLATFORMS
x86_64-linux-musl x86_64-linux-musl
DEPENDENCIES DEPENDENCIES
bcrypt (~> 3.1.7)
bootsnap bootsnap
brakeman brakeman
capybara capybara

View file

@ -1,4 +1,14 @@
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has. # Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
allow_browser versions: :modern allow_browser versions: :modern
def logged_in?
if session[:user_id] then true else false end
end
def current_user
if logged_in?
session[:user_id]
end
end
end end

View file

@ -0,0 +1,21 @@
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_path, notice: "Logged in!"
else
flash.now[:alert] = "Invalid email or password"
render :new, status: :unprocessable_entity
end
end
def destroy
session[:user_id] = nil
redirect_to root_path
end
end

View file

@ -0,0 +1,25 @@
class Test::ImagesController < ApplicationController
def index
@images = Image.all
@image = Image.new
end
def create
@image = Image.new(image_params)
if @image.save
respond_to do |format|
format.turbo_stream
format.html { redirect_to test_images_path }
end
else
render :index, status: :unprocessable_entity
end
end
private
def image_params
params.require(:image).permit(:title, :file)
end
end

View file

@ -0,0 +1,16 @@
class UsersController < ApplicationController
def new
end
def create
end
def edit
end
def update
end
def destroy
end
end

View file

@ -0,0 +1,2 @@
module SessionsHelper
end

View file

@ -0,0 +1,2 @@
module Test::ImagesHelper
end

View file

@ -0,0 +1,2 @@
module UsersHelper
end

8
app/models/image.rb Normal file
View file

@ -0,0 +1,8 @@
class Image < ApplicationRecord
has_one_attached :file
has_many :taggings, as: :taggable
has_many :tags, through: :taggings
validates :title, :file, presence: true
end

6
app/models/post.rb Normal file
View file

@ -0,0 +1,6 @@
class Post < ApplicationRecord
belongs_to :user
belongs_to :image
has_many :taggings, as: :taggable
has_many :tags, through: :taggings
end

5
app/models/tag.rb Normal file
View file

@ -0,0 +1,5 @@
class Tag < ApplicationRecord
has_many :taggings
has_many :posts, through: :taggings, source: :taggable, source_type: "Post"
has_many :images, through: :taggings, source: :taggable, source_type: "Image"
end

4
app/models/tagging.rb Normal file
View file

@ -0,0 +1,4 @@
class Tagging < ApplicationRecord
belongs_to :tag
belongs_to :taggable, polymorphic: true
end

6
app/models/user.rb Normal file
View file

@ -0,0 +1,6 @@
class User < ApplicationRecord
has_secure_password
has_many :posts
validates :name, :status, :email, :password_digest, presence: true
end

View file

@ -0,0 +1,2 @@
<h1>Sessions#destroy</h1>
<p>Find me in app/views/sessions/destroy.html.erb</p>

View file

@ -0,0 +1,2 @@
<h1>Sessions#new</h1>
<p>Find me in app/views/sessions/new.html.erb</p>

View file

@ -0,0 +1,6 @@
<div class="image-entry">
<h3><%= image.title %></h3>
<% if image.file.attached? %>
<%= image_tag image.file, width: 300 %>
<% end %>
</div>

View file

@ -0,0 +1 @@
<%= turbo_stream.prepend "images", partial: "test/images/image", locals: { image: @image } %>

View file

@ -0,0 +1,20 @@
<h1>Image Upload (Test)</h1>
<%= form_with model: @image, url: test_images_path, data: { turbo_stream: true } do |form| %>
<%= form.label :title %>
<%= form.text_field :title %><br>
<%= form.label :file %>
<%= form.file_field :file %><br>
<%= form.submit "Upload" %>
<% end %>
<hr>
<h2>Uploaded Images</h2>
<div id="images">
<%= turbo_frame_tag "images" do %>
<%= render @images %>
<% end %>
</div>

View file

@ -0,0 +1,2 @@
<h1>Users#create</h1>
<p>Find me in app/views/users/create.html.erb</p>

View file

@ -0,0 +1,2 @@
<h1>Users#new</h1>
<p>Find me in app/views/users/new.html.erb</p>

View file

@ -1,5 +1,12 @@
Rails.application.routes.draw do Rails.application.routes.draw do
resources :notes resources :users, only: [ :new, :create, :edit, :update, :destroy ]
resource :sessions, only: [ :new, :create, :destroy ]
namespace :test do
resources :images, only: [ :index, :create ]
end
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
@ -11,5 +18,5 @@ Rails.application.routes.draw do
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker # get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# Defines the root path route ("/") # Defines the root path route ("/")
# root "posts#index" root "images#index"
end end

View file

@ -0,0 +1,57 @@
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
def change
# Use Active Record's configured type for primary and foreign keys
primary_key_type, foreign_key_type = primary_and_foreign_key_types
create_table :active_storage_blobs, id: primary_key_type do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.string :service_name, null: false
t.bigint :byte_size, null: false
t.string :checksum
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :key ], unique: true
end
create_table :active_storage_attachments, id: primary_key_type do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
t.references :blob, null: false, type: foreign_key_type
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
create_table :active_storage_variant_records, id: primary_key_type do |t|
t.belongs_to :blob, null: false, index: false, type: foreign_key_type
t.string :variation_digest, null: false
t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
private
def primary_and_foreign_key_types
config = Rails.configuration.generators
setting = config.options[config.orm][:primary_key_type]
primary_key_type = setting || :primary_key
foreign_key_type = setting || :bigint
[ primary_key_type, foreign_key_type ]
end
end

View file

@ -0,0 +1,9 @@
class CreateImages < ActiveRecord::Migration[8.0]
def change
create_table :images do |t|
t.string :title
t.timestamps
end
end
end

View file

@ -0,0 +1,12 @@
class CreateUsers < ActiveRecord::Migration[8.0]
def change
create_table :users do |t|
t.string :name
t.string :status
t.string :email
t.string :password_digest
t.timestamps
end
end
end

View file

@ -0,0 +1,5 @@
class DropNotesTable < ActiveRecord::Migration[8.0]
def change
drop_table :notes
end
end

View file

@ -0,0 +1,14 @@
class CreatePosts < ActiveRecord::Migration[8.0]
def change
create_table :posts do |t|
t.string :title
t.text :content
t.boolean :pinned
t.references :user, null: false, foreign_key: true
t.references :image, null: false, foreign_key: true
t.string :type
t.timestamps
end
end
end

View file

@ -0,0 +1,10 @@
class CreateTags < ActiveRecord::Migration[8.0]
def change
create_table :tags do |t|
t.string :title
t.string :color
t.timestamps
end
end
end

View file

@ -0,0 +1,10 @@
class CreateTaggings < ActiveRecord::Migration[8.0]
def change
create_table :taggings do |t|
t.references :tag, null: false, foreign_key: true
t.references :taggable, polymorphic: true, null: false
t.timestamps
end
end
end

78
db/schema.rb generated
View file

@ -10,11 +10,83 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_05_06_085403) do ActiveRecord::Schema[8.0].define(version: 2025_05_15_135623) do
create_table "notes", force: :cascade do |t| create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.string "service_name", null: false
t.bigint "byte_size", null: false
t.string "checksum"
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "active_storage_variant_records", force: :cascade do |t|
t.bigint "blob_id", null: false
t.string "variation_digest", null: false
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
create_table "images", force: :cascade do |t|
t.string "title" t.string "title"
t.text "body"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "content"
t.boolean "pinned"
t.integer "user_id", null: false
t.integer "image_id", null: false
t.string "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["image_id"], name: "index_posts_on_image_id"
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "taggings", force: :cascade do |t|
t.integer "tag_id", null: false
t.string "taggable_type", null: false
t.integer "taggable_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["tag_id"], name: "index_taggings_on_tag_id"
t.index ["taggable_type", "taggable_id"], name: "index_taggings_on_taggable"
end
create_table "tags", force: :cascade do |t|
t.string "title"
t.string "color"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "status"
t.string "email"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "posts", "images"
add_foreign_key "posts", "users"
add_foreign_key "taggings", "tags"
end end

View file

@ -0,0 +1,19 @@
require "test_helper"
class SessionsControllerTest < ActionDispatch::IntegrationTest
test "should get new" do
get new_sessions_path
assert_response :success
end
test "should get create" do
post sessions_path, params: { email: "test@email.com", password: "testpassword" }
assert_redirected_to root_path
end
test "should get destroy" do
post sessions_path, params: { email: "test@email.com", password: "testpassword" }
delete sessions_path
assert_redirected_to root_path
end
end

View file

@ -0,0 +1,21 @@
require "test_helper"
include ActiveJob::TestHelper
class Test::ImagesControllerTest < ActionDispatch::IntegrationTest
test "should get index" do
get test_images_path
assert_response :success
end
test "should get create" do
file = fixture_file_upload("test_image.jpg", "image/jpeg")
post test_images_path, params: { image: { file: file, title: "test" } }
assert_redirected_to test_images_path
end
teardown do
perform_enqueued_jobs do
ActiveStorage::Blob.all.each(&:purge_later)
end
end
end

View file

@ -0,0 +1,38 @@
require "test_helper"
class UsersControllerTest < ActionDispatch::IntegrationTest
setup do
@user = users(:one) # Assuming you have a fixture or factory for @user
end
test "should get new" do
get new_user_path
assert_response :success
end
test "should get create" do
post users_path
assert_response :success
# post users_path, params: { user: { username: "testuser", password: "password123" } }
# assert_redirected_to user_path(User.last)
end
test "should get edit" do
get edit_user_path(@user)
assert_response :success
end
test "should get update" do
patch user_path(@user)
assert_response :success
# Probably also assert a successful redirect later and push correct data params
end
test "should get destroy" do
delete user_path(@user)
assert_response :success
# Possibly this one too I suppose
end
end

View file

@ -0,0 +1 @@
# Keep these, they're silly

BIN
test/fixtures/files/mermaid_template.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
test/fixtures/files/test_image.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 KiB

View file

@ -2,8 +2,6 @@
one: one:
title: MyString title: MyString
body: MyText
two: two:
title: MyString title: MyString
body: MyText

17
test/fixtures/posts.yml vendored Normal file
View file

@ -0,0 +1,17 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
title: MyString
content: MyText
pinned: false
user: one
image: one
type:
two:
title: MyString
content: MyText
pinned: false
user: two
image: two
type:

11
test/fixtures/taggings.yml vendored Normal file
View file

@ -0,0 +1,11 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
tag: one
taggable: one
taggable_type: Taggable
two:
tag: two
taggable: two
taggable_type: Taggable

9
test/fixtures/tags.yml vendored Normal file
View file

@ -0,0 +1,9 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
title: MyString
color: MyString
two:
title: MyString
color: MyString

13
test/fixtures/users.yml vendored Normal file
View file

@ -0,0 +1,13 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
name: testuser
status: test
email: test@email.com
password_digest: <%= BCrypt::Password.create('testpassword') %>
two:
name: testuser2
status: dead
email: tester2@email.com
password_digest: <%= BCrypt::Password.create('tpass2') %>

View file

@ -0,0 +1,7 @@
require "test_helper"
class ImageTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end

View file

@ -1,6 +1,6 @@
require "test_helper" require "test_helper"
class NoteTest < ActiveSupport::TestCase class PostTest < ActiveSupport::TestCase
# test "the truth" do # test "the truth" do
# assert true # assert true
# end # end

7
test/models/tag_test.rb Normal file
View file

@ -0,0 +1,7 @@
require "test_helper"
class TagTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end

View file

@ -0,0 +1,7 @@
require "test_helper"
class TaggingTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end

7
test/models/user_test.rb Normal file
View file

@ -0,0 +1,7 @@
require "test_helper"
class UserTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end