Compare commits

..

No commits in common. "93359a5b599c71eb05316802a31646737b3ed0a1" and "d1395c780afbf54a1c07f09c69239e2316e48454" have entirely different histories.

45 changed files with 152 additions and 575 deletions

View File

@ -1,4 +0,0 @@
#!/usr/bin/env bash
ln .git-hooks/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
GREEN='\033[0;32m'
AMBER='\033[0;33m'
RED='\033[0;31m'
CLEAR_COLOR='\033[0m'
function run_command {
local COMMAND=$1
local COMMAND_NAME=$2
echo -e "${AMBER}Running $COMMAND_NAME…${AMBER}"
$COMMAND &>/dev/null
if [[ $? -ne 0 ]] ; then
echo -e "${RED}❌ $COMMAND_NAME failed${CLEAR_COLOR}"
exit 1
else
echo -e "${GREEN}✓ $COMMAND_NAME passed${CLEAR_COLOR}"
fi
}
run_command "brakeman --format html -o ../tmp/brakeman.html" "Brakeman"
run_command "bundle exec rubocop" "Rubocop"
run_command "bundle exec rails test" "test suite"

View File

@ -3,7 +3,7 @@ source "https://rubygems.org"
ruby file: "./.ruby-version" ruby file: "./.ruby-version"
gem "rails", "~> 7.1.3", ">= 7.1.3.2" gem "rails", "~> 7.1.3", ">= 7.1.3.2"
gem "propshaft" gem "sprockets-rails"
gem "pg" gem "pg"
gem "puma", ">= 5.0" gem "puma", ">= 5.0"
gem "importmap-rails" gem "importmap-rails"

View File

@ -1,35 +1,35 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.1.3.3) actioncable (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
actionmailbox (7.1.3.3) actionmailbox (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.1.3.3) actionmailer (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
actionview (= 7.1.3.3) actionview (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
actionpack (7.1.3.3) actionpack (7.1.3.2)
actionview (= 7.1.3.3) actionview (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
racc racc
rack (>= 2.2.4) rack (>= 2.2.4)
@ -37,35 +37,35 @@ GEM
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
actiontext (7.1.3.3) actiontext (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.1.3.3) actionview (7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.11) erubi (~> 1.11)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
activejob (7.1.3.3) activejob (7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.1.3.3) activemodel (7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
activerecord (7.1.3.3) activerecord (7.1.3.2)
activemodel (= 7.1.3.3) activemodel (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
timeout (>= 0.4.0) timeout (>= 0.4.0)
activestorage (7.1.3.3) activestorage (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
marcel (~> 1.0) marcel (~> 1.0)
activesupport (7.1.3.3) activesupport (7.1.3.2)
base64 base64
bigdecimal bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
@ -80,7 +80,7 @@ GEM
ast (2.4.2) ast (2.4.2)
base64 (0.2.0) base64 (0.2.0)
bcrypt (3.1.20) bcrypt (3.1.20)
bigdecimal (3.1.8) bigdecimal (3.1.7)
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.18.3) bootsnap (1.18.3)
msgpack (~> 1.2) msgpack (~> 1.2)
@ -105,17 +105,17 @@ GEM
erubi (1.12.0) erubi (1.12.0)
globalid (1.2.1) globalid (1.2.1)
activesupport (>= 6.1) activesupport (>= 6.1)
i18n (1.14.5) i18n (1.14.4)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
importmap-rails (2.0.1) importmap-rails (2.0.1)
actionpack (>= 6.0.0) actionpack (>= 6.0.0)
activesupport (>= 6.0.0) activesupport (>= 6.0.0)
railties (>= 6.0.0) railties (>= 6.0.0)
io-console (0.7.2) io-console (0.7.2)
irb (1.13.1) irb (1.12.0)
rdoc (>= 4.0.0) rdoc
reline (>= 0.4.2) reline (>= 0.4.2)
jbuilder (2.12.0) jbuilder (2.11.5)
actionview (>= 5.0.0) actionview (>= 5.0.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
json (2.7.2) json (2.7.2)
@ -131,10 +131,10 @@ GEM
marcel (1.0.4) marcel (1.0.4)
matrix (0.4.2) matrix (0.4.2)
mini_mime (1.1.5) mini_mime (1.1.5)
minitest (5.23.1) minitest (5.22.3)
msgpack (1.7.2) msgpack (1.7.2)
mutex_m (0.2.0) mutex_m (0.2.0)
net-imap (0.4.11) net-imap (0.4.10)
date date
net-protocol net-protocol
net-pop (0.1.2) net-pop (0.1.2)
@ -143,36 +143,31 @@ GEM
timeout timeout
net-smtp (0.5.0) net-smtp (0.5.0)
net-protocol net-protocol
nio4r (2.7.3) nio4r (2.7.1)
nokogiri (1.16.5-aarch64-linux) nokogiri (1.16.4-aarch64-linux)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.16.5-arm-linux) nokogiri (1.16.4-arm-linux)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.16.5-arm64-darwin) nokogiri (1.16.4-arm64-darwin)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.16.5-x86-linux) nokogiri (1.16.4-x86-linux)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.16.5-x86_64-darwin) nokogiri (1.16.4-x86_64-darwin)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.16.5-x86_64-linux) nokogiri (1.16.4-x86_64-linux)
racc (~> 1.4) racc (~> 1.4)
parallel (1.24.0) parallel (1.24.0)
parser (3.3.1.0) parser (3.3.0.5)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
pg (1.5.6) pg (1.5.6)
propshaft (0.9.0)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
psych (5.1.2) psych (5.1.2)
stringio stringio
public_suffix (5.0.5) public_suffix (5.0.5)
puma (6.4.2) puma (6.4.2)
nio4r (~> 2.0) nio4r (~> 2.0)
racc (1.8.0) racc (1.7.3)
rack (3.0.11) rack (3.0.10)
rack-session (2.0.0) rack-session (2.0.0)
rack (>= 3.0.0) rack (>= 3.0.0)
rack-test (2.1.0) rack-test (2.1.0)
@ -180,20 +175,20 @@ GEM
rackup (2.1.0) rackup (2.1.0)
rack (>= 3) rack (>= 3)
webrick (~> 1.8) webrick (~> 1.8)
rails (7.1.3.3) rails (7.1.3.2)
actioncable (= 7.1.3.3) actioncable (= 7.1.3.2)
actionmailbox (= 7.1.3.3) actionmailbox (= 7.1.3.2)
actionmailer (= 7.1.3.3) actionmailer (= 7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
actiontext (= 7.1.3.3) actiontext (= 7.1.3.2)
actionview (= 7.1.3.3) actionview (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activemodel (= 7.1.3.3) activemodel (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.1.3.3) railties (= 7.1.3.2)
rails-dom-testing (2.2.0) rails-dom-testing (2.2.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
minitest minitest
@ -201,9 +196,9 @@ GEM
rails-html-sanitizer (1.6.0) rails-html-sanitizer (1.6.0)
loofah (~> 2.21) loofah (~> 2.21)
nokogiri (~> 1.14) nokogiri (~> 1.14)
railties (7.1.3.3) railties (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
irb irb
rackup (>= 1.0.0) rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
@ -211,14 +206,13 @@ GEM
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
rainbow (3.1.1) rainbow (3.1.1)
rake (13.2.1) rake (13.2.1)
rdoc (6.7.0) rdoc (6.6.3.1)
psych (>= 4.0.0) psych (>= 4.0.0)
regexp_parser (2.9.2) regexp_parser (2.9.0)
reline (0.5.7) reline (0.5.1)
io-console (~> 0.5) io-console (~> 0.5)
rexml (3.2.8) rexml (3.2.6)
strscan (>= 3.0.9) rubocop (1.63.1)
rubocop (1.64.0)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0) language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)
@ -229,15 +223,15 @@ GEM
rubocop-ast (>= 1.31.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0) unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.31.3) rubocop-ast (1.31.2)
parser (>= 3.3.1.0) parser (>= 3.3.0.4)
rubocop-minitest (0.35.0) rubocop-minitest (0.35.0)
rubocop (>= 1.61, < 2.0) rubocop (>= 1.61, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0)
rubocop-performance (1.21.0) rubocop-performance (1.21.0)
rubocop (>= 1.48.1, < 2.0) rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rails (2.25.0) rubocop-rails (2.24.1)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0) rubocop (>= 1.33.0, < 2.0)
@ -249,15 +243,21 @@ GEM
rubocop-rails rubocop-rails
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
rubyzip (2.3.2) rubyzip (2.3.2)
selenium-webdriver (4.21.1) selenium-webdriver (4.19.0)
base64 (~> 0.2) base64 (~> 0.2)
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)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
stimulus-rails (1.3.3) stimulus-rails (1.3.3)
railties (>= 6.0.0) railties (>= 6.0.0)
stringio (3.1.0) stringio (3.1.0)
strscan (3.1.0)
thor (1.3.1) thor (1.3.1)
timeout (0.4.1) timeout (0.4.1)
turbo-rails (2.0.5) turbo-rails (2.0.5)
@ -279,7 +279,7 @@ GEM
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.6.15) zeitwerk (2.6.13)
PLATFORMS PLATFORMS
aarch64-linux aarch64-linux
@ -297,11 +297,11 @@ DEPENDENCIES
importmap-rails importmap-rails
jbuilder jbuilder
pg pg
propshaft
puma (>= 5.0) puma (>= 5.0)
rails (~> 7.1.3, >= 7.1.3.2) rails (~> 7.1.3, >= 7.1.3.2)
rubocop-rails-omakase rubocop-rails-omakase
selenium-webdriver selenium-webdriver
sprockets-rails
stimulus-rails stimulus-rails
turbo-rails turbo-rails
tzinfo-data tzinfo-data

View File

@ -1,26 +1,17 @@
# Tabletop Companion # Forg
Tabletop Companion is a lightweight way to assist you playing tabletop games, online with Forg is a _Family ORGaniser_.
the video chat software of your choice or offline at a physical table.
It will allow you to:
- Set and assign todos
- Includes regularly scheduled tasks, such as housework
- Set a meal plan
- Allows for advanced reminders to cook/purchase ingredients/defrost
- Manage a shopping list
## Development setup ## Development setup
Spin up the application with `./bin/setup`. Spin up the application with `./bin/setup`.
Run tests with `rails test`. Run tests with `rails test`.
### Git hooks
There is a pre-commit git hook stored in .git-hooks which can be installed by running `.git-hooks/install.bash`.
The hooks:
- Run Rubocop
- Run tests
- Run Brakeman
### Brakeman
If Brakeman issues are introduced, they should be immediately fixed or ignored with a note as to why it
is not a real issue. To do so, run `bundle exec brakeman -I`.

View File

@ -0,0 +1,15 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/

View File

@ -2,12 +2,4 @@
--inset-bg-color: #eee; --inset-bg-color: #eee;
--border-radius: .5em; --border-radius: .5em;
--button-bg-color: #333;
--button-text-color: #fff;
--button-hover-bg-color: #555;
--button-hover-text-color: #fff;
--notice-bg-color: #5cb85c;
--notice-text-color: #fff;
} }

View File

@ -13,13 +13,6 @@ main {
flex-direction: column; flex-direction: column;
} }
aside.flash {
background-color: var(--notice-bg-color);
color: var(--notice-text-color);
padding: 1em;
border-radius: var(--border-radius);
}
section.inset { section.inset {
width: 70%; width: 70%;
max-width: 60em; max-width: 60em;
@ -32,25 +25,3 @@ section.inset {
h1, h2 { h1, h2 {
text-align: center; text-align: center;
} }
header nav {
ul {
display: flex;
justify-content: center;
}
li {
list-style-type: none;
padding: 0 .5em;
}
a:link, a:visited {
background-color: var(--button-bg-color);
color: var(--button-text-color);
border-radius: var(--border-radius);
text-decoration: none;
padding: .5em;
}
a:hover {
background-color: var(--button-hover-bg-color);
color: var(--button-hover-text-color);
}
}

View File

@ -1,57 +0,0 @@
class Admin::GameSystemsController < AdminController
before_action :set_game_system, only: [ :show, :edit, :update, :destroy ]
def index
@game_systems = GameSystem.all
end
def show
end
def new
@game_system = GameSystem.new
end
def create
@game_system = GameSystem.new(game_system_params)
if @game_system.save
redirect_to admin_game_system_path(@game_system), notice: t(".success", name: @game_system.name)
else
flash.now[:alert] = t(".error", name: @game_system.name)
render :new, status: :unprocessable_entity
end
end
def edit
end
def update
if @game_system.update(game_system_params)
redirect_to admin_game_system_path(@game_system), notice: t(".success", name: @game_system.name)
else
flash.now[:alert] = t(".error", name: @game_system.name)
render :edit, status: :unprocessable_entity
end
end
def destroy
name = @game_system.name
if @game_system.destroy
redirect_to admin_game_systems_path, notice: t(".success", name:)
else
flash[:alert] = t(".error", name:)
redirect_to admin_game_systems_path, alert: t(".error")
end
end
private
def game_system_params
params.require(:game_system).permit(
:name,
)
end
def set_game_system
@game_system = GameSystem.find(params[:id])
end
end

View File

@ -1,14 +0,0 @@
class AdminController < ApplicationController
layout "admin"
before_action :authenticate_user_as_admin
def index
end
private
def authenticate_user_as_admin
head :forbidden unless Current.user&.admin?
end
end

View File

@ -4,6 +4,7 @@ class ApplicationController < ActionController::Base
private private
def authenticate def authenticate
Rails.logger.error "Session: #{session.inspect}"
if authenticated_user = User.find_by(id: session[:user_id]) if authenticated_user = User.find_by(id: session[:user_id])
Current.user = authenticated_user Current.user = authenticated_user
else else

View File

@ -1,4 +0,0 @@
class TablesController < ApplicationController
def index
end
end

View File

@ -0,0 +1,4 @@
class TodosController < ApplicationController
def index
end
end

View File

@ -5,12 +5,12 @@ class UserMailer < ApplicationMailer
@user = params[:user] @user = params[:user]
@token = params[:token] @token = params[:token]
mail(to: @user.email, subject: "[Tabletop Companion] Verify your email") mail(to: @user.email, subject: "[Forg] Verify your email")
end end
def email_verified def email_verified
@user = params[:user] @user = params[:user]
mail(to: @user.email, subject: "[Tabletop Companion] Your email has been verified") mail(to: @user.email, subject: "[Forg] Your email has been verified")
end end
end end

View File

@ -1,5 +0,0 @@
class GameSystem < ApplicationRecord
validates :name, presence: true,
uniqueness: true,
length: { maximum: 100 }
end

View File

@ -1,3 +0,0 @@
class SiteRole < ApplicationRecord
validates :name, presence: true
end

View File

@ -1,6 +1,4 @@
class User < ApplicationRecord class User < ApplicationRecord
has_and_belongs_to_many :site_roles
has_secure_password has_secure_password
generates_token_for :password_reset, expires_in: 4.hours do generates_token_for :password_reset, expires_in: 4.hours do
password_salt.last(10) # Invalidates when password changed password_salt.last(10) # Invalidates when password changed
@ -37,8 +35,4 @@ class User < ApplicationRecord
"#{first_name} #{last_name}" "#{first_name} #{last_name}"
end end
def admin?
site_roles.include? SiteRole.find_by(name: "Admin")
end
end end

View File

@ -1,8 +0,0 @@
<% # locals: (game_system: @game_system, button_text:, url:) %>
<%= form_with model: @game_system, url: do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit button_text %>
<% end %>

View File

@ -1,4 +0,0 @@
<h2><%= t(".edit", name: @game_system.name) %></h2>
<%= render partial: "form",
locals: { button_text: t(".update", name: @game_system.name), url: admin_game_system_path(@game_system) } %>

View File

@ -1,9 +0,0 @@
<% content_for :title, t(".game_systems") %>
<%= link_to t(".new_game_system"), new_admin_game_system_path %>
<% @game_systems.each do |game_system| %>
<div id=<%= dom_id(game_system) %> class="game-system">
<%= link_to game_system.name, admin_game_system_path(game_system) %>
</div>
<% end %>

View File

@ -1,3 +0,0 @@
<h2><%= t(".new") %></h2>
<%= render partial: "form", locals: { button_text: t(".create"), url: admin_game_systems_path } %>

View File

@ -1,6 +0,0 @@
<h2><%= @game_system.name %></h2>
<%= link_to t("edit"), edit_admin_game_system_path(@game_system) %>
<%= link_to t("delete"), admin_game_system_path(@game_system),
data: { turbo_method: :delete, turbo_confirm: t(".confirm_delete", name: @game_system.name) } %>

View File

@ -1,2 +0,0 @@
<% content_for :title, t(".dashboard") %>
<%= t(".intro") %>

View File

@ -1,11 +0,0 @@
<% content_for :submenu do %>
<h2><%= t("administration") %>: <%= content_for :title %></h2>
<nav>
<ul>
<li><%= link_to t(".dashboard"), admin_index_path %></li>
<li><%= link_to t(".game_systems"), admin_game_systems_path %></li>
</ul>
</nav>
<% end %>
<%= render template: "layouts/application" %>

View File

@ -1,12 +1,12 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title><%= "#{yield(:title)} | " if content_for? :title %><%= t("site_name") %></title> <title><%= "#{yield(:title)} | " if content_for? :title %><%= t("forg") %></title>
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %> <%= csrf_meta_tags %>
<%= csp_meta_tag %> <%= csp_meta_tag %>
<%= stylesheet_link_tag :all, "data-turbo-track": "reload" %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %> <%= javascript_importmap_tags %>
<meta name="turbo-refresh-method" content="morph"> <meta name="turbo-refresh-method" content="morph">
<meta name="turbo-refresh-scroll" content="preserve"> <meta name="turbo-refresh-scroll" content="preserve">
@ -14,24 +14,19 @@
<body> <body>
<header> <header>
<h1><%= link_to t("site_name"), root_path %></h1> <h1><%= link_to t("forg"), root_path %></h1>
<nav>
<ul>
<% if logged_in? %>
<li><%= link_to t("log_out"), logout_path, data: {turbo_method: :delete} %></li>
<% if Current.user.admin? %>
<li><%= link_to t("administration"), admin_index_path %></li>
<% end %>
<% else %>
<li><%= link_to t("log_in"), login_path %></li>
<li><%= link_to t("sign_up"), new_user_path %></li>
<% end %>
</ul>
</nav>
</header> </header>
<nav>
<ul>
<li><%= link_to t("forg"), root_path %></li>
<% if logged_in? %>
<li><%= link_to t("log_out"), logout_path, data: {turbo_method: :delete} %></li>
<% else %>
<li><%= link_to t("log_in"), login_path %></li>
<li><%= link_to t("sign_up"), new_user_path %></li>
<% end %>
<%= render partial: "shared/flash_messages" %> <%= render partial: "shared/flash_messages" %>
<main> <main>
<%= yield(:submenu) if content_for?(:submenu) %>
<%= yield %> <%= yield %>
</main> </main>
</body> </body>

View File

@ -6,7 +6,7 @@ require "rails/all"
# you've limited to :test, :development, or :production. # you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups) Bundler.require(*Rails.groups)
module TabletopCompanion module Forg
class Application < Rails::Application class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version. # Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.1 config.load_defaults 7.1

View File

@ -7,4 +7,4 @@ test:
production: production:
adapter: redis adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: tabletop_companion_production channel_prefix: forg_production

View File

@ -9,12 +9,12 @@ default: &default
development: development:
<<: *default <<: *default
database: tabletop_companion_development database: forg_development
test: test:
<<: *default <<: *default
database: tabletop_companion_test database: forg_test
production: production:
<<: *default <<: *default
database: tabletop_companion_production database: forg_production

View File

@ -1,56 +1,24 @@
en: en:
site_name: Tabletop Companion forg: Forg
administration: Administration
log_in: Log in log_in: Log in
log_out: Log out log_out: Log out
sign_up: Sign up sign_up: Sign up
not_authenticated: You need to log in to access this page. not_authenticated: You need to log in to access this page.
edit: Edit
delete: Delete
layouts: layouts:
admin:
dashboard: Dashboard
game_systems: Game Systems
mailer: mailer:
greeting: "Hello, %{name}" greeting: "Hello, %{name}"
sign_off: | sign_off: |
See you soon, See you soon,
The Tabletop Companion team The Forg team
sign_off_html: "<p>See you soon,<br>The Tabletop Companion team</p>" sign_off_html: "<p>See you soon,<br>The Forg team</p>"
account_verifications: account_verifications:
show: show:
success: "Thanks for verifying your email address! You can now log in." success: "Thanks for verifying your email address! You can now log in."
error: "Invalid token, could not verify your account." error: "Invalid token, could not verify your account."
admin:
index:
dashboard: Dashboard
intro: With great power comes great responsibility
game_systems:
error: Error
index:
game_systems: Game systems
new_game_system: New game system
new:
new: New game system
create: Add game system
create:
success: “%{name}” has been created.
error: “%{name}” could not be created.
show:
confirm_delete: Are you sure you want to delete “%{name}”?
edit:
edit: Edit %{name}
update: Update %{name}
update:
success: Successfully updated “%{name}”.
error: “%{name}” could not be updated.
destroy:
success: Successfully deleted “%{name}”.
error: “%{name}” could not be deleted.
sessions: sessions:
create: create:
success: "Hello, %{name}!" success: "Hello, %{name}!"
error: "Could not sign in. Please check your username and password." error: "Could not sign in. Please check your email and password."
new: new:
log_in: Log in log_in: Log in
destroy: destroy:
@ -63,16 +31,16 @@ en:
sign_up: Sign up sign_up: Sign up
create: create:
error: "Could not create account: %{error}" error: "Could not create account: %{error}"
success: "Thanks for joining Tabletop Companion, %{name}! Please check your email to verify your address." success: "Thanks for joining Forg, %{name}! Please check your email to verify your address."
user_mailer: user_mailer:
email_verified: email_verified:
content: |- content: |-
Thanks for verifying your email address, and welcome to Tabletop Companion! Thanks for verifying your email address, and welcome to Forg!
You can now go ahead and log in. Enjoy! You can now go ahead and log in. Enjoy!
email_verification: email_verification:
content: |- content: |-
If you did not sign up for Tabletop Companion, please ignore this email. If you did not sign up for Forg, please ignore this email.
Otherwise, please visit the link below to verify your email address. Otherwise, please visit the link below to verify your email address.

View File

@ -1,21 +1,15 @@
Rails.application.routes.draw do Rails.application.routes.draw do
default_url_options host: "summonplayer.com" get 'todos/index'
default_url_options host: "forg-app.com"
root "tables#index" root "todos#index"
get "login" => "sessions#new", as: :login get "login" => "sessions#new", as: :login
delete "logout" => "sessions#destroy", as: :logout delete "logout" => "sessions#destroy", as: :logout
resources :users, only: [ :new, :create ] resources :users, only: %i[new create]
resources :account_verifications, only: [ :show ] resources :account_verifications, only: %i[show]
resources :sessions, only: [ :new, :create, :destroy ] resources :sessions, only: %i[new create destroy]
resources :tables, only: [ :index ]
resources :admin, only: [ :index ]
namespace :admin do
resources :game_systems
end
get "up" => "rails/health#show", as: :rails_health_check get "up" => "rails/health#show", as: :rails_health_check
end end

View File

@ -1,9 +0,0 @@
class CreateGameSystems < ActiveRecord::Migration[7.1]
def change
create_table :game_systems do |t|
t.string :name, null: false
t.timestamps
end
end
end

View File

@ -1,14 +0,0 @@
class CreateUserRoles < ActiveRecord::Migration[7.1]
def change
create_table :site_roles do |t|
t.string :name, null: false
t.timestamps
end
create_table :site_roles_users do |t|
t.belongs_to :user
t.belongs_to :site_role
end
end
end

View File

@ -1,7 +0,0 @@
class AddUniqueIndexToGameSystemName < ActiveRecord::Migration[7.1]
def change
add_index :game_systems, :name, unique: true
add_check_constraint :game_systems, "length(name) <= 100", name: "chk_name_max_length"
end
end

23
db/schema.rb generated
View File

@ -10,31 +10,10 @@
# #
# 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[7.1].define(version: 2024_05_26_102908) do ActiveRecord::Schema[7.1].define(version: 2024_04_14_122652) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
create_table "game_systems", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["name"], name: "index_game_systems_on_name", unique: true
t.check_constraint "length(name::text) <= 100", name: "chk_name_max_length"
end
create_table "site_roles", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "site_roles_users", force: :cascade do |t|
t.bigint "user_id"
t.bigint "site_role_id"
t.index ["site_role_id"], name: "index_site_roles_users_on_site_role_id"
t.index ["user_id"], name: "index_site_roles_users_on_user_id"
end
create_table "users", force: :cascade do |t| create_table "users", force: :cascade do |t|
t.string "username", limit: 20, null: false t.string "username", limit: 20, null: false
t.string "password_digest", limit: 200, null: false t.string "password_digest", limit: 200, null: false

View File

@ -1,20 +0,0 @@
require "test_helper"
class AdminGameSystemsControllerTest < ActionDispatch::IntegrationTest
test "should get game systems index if signed in as admin" do
sign_in users(:admin)
get admin_game_systems_path
assert_response :success
end
test "should not get game systems index if signed in as non-admin user" do
sign_in users(:trevor)
get admin_game_systems_path
assert_response :forbidden
end
test "should not get game systems index if not signed in" do
get admin_game_systems_path
assert_redirected_to login_path
end
end

View File

@ -1,20 +0,0 @@
require "test_helper"
class AdminControllerTest < ActionDispatch::IntegrationTest
test "should get index if signed in as admin" do
sign_in users(:admin)
get admin_index_url
assert_response :success
end
test "should not get index if signed in as non-admin user" do
sign_in users(:trevor)
get admin_index_url
assert_response :forbidden
end
test "should not get index if not signed in" do
get admin_index_url
assert_redirected_to login_path
end
end

View File

@ -1,2 +0,0 @@
troika:
name: Troika

View File

@ -1,2 +0,0 @@
admin:
name: Admin

View File

@ -16,12 +16,6 @@ unverified:
last_name: User last_name: User
verified: false verified: false
admin:
<<: *DEFAULTS
first_name: Admin
last_name: User
site_roles: admin
<% 1.upto(10) do |i| %> <% 1.upto(10) do |i| %>
user_<%= i %>: user_<%= i %>:
<<: *DEFAULTS <<: *DEFAULTS

View File

@ -1,64 +0,0 @@
require "test_helper"
class AdminGameSystemsIntegrationTest < ActionDispatch::IntegrationTest
test "index should show most all game systems" do
sign_in users(:admin)
get admin_game_systems_path
assert_response :success
assert_select ".game-system", GameSystem.all.size
end
test "show should show game system" do
sign_in users(:admin)
get admin_game_system_path(game_systems(:troika))
assert_response :success
assert_select "h2", game_systems(:troika).name
end
test "new should show form to create new game system" do
sign_in users(:admin)
get new_admin_game_system_path
assert_response :success
assert_select "form[action=?][method=?]", admin_game_systems_path, "post"
end
test "create should create new game system" do
sign_in users(:admin)
assert_difference "GameSystem.count", 1 do
post admin_game_systems_path, params: { game_system: { name: "Test Game System" } }
end
assert_redirected_to admin_game_system_path(GameSystem.last)
end
test "create should fail if game system already exists" do
sign_in users(:admin)
assert_no_difference "GameSystem.count" do
post admin_game_systems_path, params: { game_system: { name: game_systems(:troika).name } }
end
assert_response :unprocessable_entity
end
test "edit should show form to edit game system" do
sign_in users(:admin)
get edit_admin_game_system_path(game_systems(:troika))
assert_response :success
assert_select "form[action=?][method=?]", admin_game_system_path(game_systems(:troika)), "post"
end
test "update should update game system" do
sign_in users(:admin)
patch admin_game_system_path(game_systems(:troika)), params: { game_system: { name: "Test Game System" } }
assert_redirected_to admin_game_system_path(game_systems(:troika))
end
test "destroy should destroy game system" do
sign_in users(:admin)
assert_difference "GameSystem.count", -1 do
delete admin_game_system_path(game_systems(:troika))
end
assert_redirected_to admin_game_systems_path
end
end

View File

@ -1,11 +0,0 @@
require "test_helper"
class PermissionsTest < ActionDispatch::IntegrationTest
test "admin? returns true for users with an admin role" do
user = users(:trevor)
assert_not user.admin?
user.site_roles << site_roles(:admin)
assert user.admin?
end
end

View File

@ -1,7 +0,0 @@
require "test_helper"
class GameSystemTest < ActiveSupport::TestCase
test "name must exist" do
assert_must_exist(game_systems(:troika), :name)
end
end

View File

@ -1,7 +0,0 @@
require "test_helper"
class UserRoleTest < ActiveSupport::TestCase
test "name must exist" do
assert_must_exist(site_roles(:admin), :name)
end
end

View File

@ -21,9 +21,5 @@ module ActiveSupport
def attr_name(klass, attr) def attr_name(klass, attr)
klass.human_attribute_name(attr) klass.human_attribute_name(attr)
end end
def sign_in(user, password: "password")
post sessions_path, params: { username: user.username, password: password }
end
end end
end end