From ea3a818c295d28055a1a7b81e0b83fb7ff329a3f Mon Sep 17 00:00:00 2001 From: Avram Walden Date: Tue, 11 Jun 2024 17:04:31 -0700 Subject: [PATCH] fix: bug fixes --- .gitignore | 2 ++ Dockerfile | 7 ++-- Gemfile.lock | 3 ++ Procfile | 1 + app/controllers/screens_controller.rb | 13 +++++-- app/controllers/users_controller.rb | 1 - .../Components/Section/Section.css.ts | 20 +++++++++++ .../Components/Section/Section.module.css | 9 ----- app/frontend/Components/Section/index.tsx | 5 +-- app/frontend/Pages/Error/index.tsx | 16 +++++++++ .../Screens/Components/Control/index.tsx | 2 +- app/frontend/types/routes.d.ts | 22 ++++-------- app/frontend/types/routes.js | 20 ++++------- app/lib/tasks/annotate.rb | 0 app/models/screen.rb | 4 ++- app/models/user.rb | 4 +-- app/policies/application_policy.rb | 4 ++- bin/docker-entrypoint | 15 ++++++-- config/environments/production.rb | 2 +- config/routes.rb | 2 +- config/secrets/credentials.yml.enc | 2 +- db/seeds/01_required.rb | 3 ++ docker_copy_files.sh | 35 +++++++++++++++++++ lib/custom_failure.rb | 3 ++ vite.config.ts | 1 + 25 files changed, 138 insertions(+), 58 deletions(-) create mode 100644 Procfile create mode 100644 app/frontend/Components/Section/Section.css.ts delete mode 100644 app/frontend/Components/Section/Section.module.css create mode 100644 app/frontend/Pages/Error/index.tsx delete mode 100644 app/lib/tasks/annotate.rb create mode 100755 docker_copy_files.sh diff --git a/.gitignore b/.gitignore index 308a133..cdfa65f 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,5 @@ node_modules # Vite uses dotenv and suggests to ignore local-only env files. See # https://vitejs.dev/guide/env-and-mode.html#env-files *.local + +/config/secrets/master.key diff --git a/Dockerfile b/Dockerfile index bf7643c..6cf4264 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,9 +27,10 @@ WORKDIR /osc # Set production environment ENV RAILS_LOG_TO_STDOUT="1" ENV RAILS_SERVE_STATIC_FILES true -ENV RAILS_ENV production +ENV RAILS_ENV=production +ENV RACK_ENV=production +ENV NODE_ENV=production # ENV BUNDLE_WITHOUT development -ENV NODE_ENV production # Install application gems COPY Gemfile Gemfile.lock ./ @@ -49,7 +50,7 @@ RUN ./docker_copy_files.sh RUN bundle exec bootsnap precompile --gemfile app/ lib/ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY -RUN SECRET_KEY_BASE=DUMMY bundle exec rails assets:precompile +RUN RACK_ENV=production RAILS_ENV=production NODE_ENV=production SECRET_KEY_BASE=DUMMY bundle exec rails assets:precompile # Entrypoint prepares the database ENTRYPOINT ["/osc/bin/docker-entrypoint"] diff --git a/Gemfile.lock b/Gemfile.lock index 06a8d56..66c94f6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -216,6 +216,8 @@ GEM net-smtp (0.5.0) net-protocol nio4r (2.7.1) + nokogiri (1.16.4-aarch64-linux) + racc (~> 1.4) nokogiri (1.16.4-arm64-darwin) racc (~> 1.4) nokogiri (1.16.4-x86_64-linux) @@ -420,6 +422,7 @@ GEM zeitwerk (2.6.13) PLATFORMS + aarch64-linux arm64-darwin-22 arm64-darwin-23 x86_64-linux diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..0ed27b4 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: bin/rails server diff --git a/app/controllers/screens_controller.rb b/app/controllers/screens_controller.rb index cc6f3c9..6449b24 100644 --- a/app/controllers/screens_controller.rb +++ b/app/controllers/screens_controller.rb @@ -5,21 +5,30 @@ class ScreensController < ApplicationController expose :screen, id: -> { params[:slug] }, scope: -> { Screen.includes_associated }, find_by: :slug expose :main_screen, -> { Screen.order(:order).first } + skip_before_action :authenticate_user!, only: [:index, :show] + # @route GET / (root) # @route GET /screens (screens) def index - redirect_to main_screen + redirect_to main_screen || new_screen_path end # @route GET /screens/:slug (screen) def show - authorize screen render inertia: "Screens/Show", props: { screen: -> { screen.render(view: :show) }, screens: -> { Screen.all.render(view: :options) }, } end + # @route GET /screens/new (new_screen) + def new + authorize Screen.new + render inertia: "Screens/New", props: { + screen: Screen.new.render(view: :form_data) + } + end + # @route GET /screens/edit (edit_screens) # @route GET /screens/:slug/edit (edit_screen) def edit diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index ced9de3..f48f901 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,6 +1,5 @@ class UsersController < ApplicationController include Searchable - include ContactableConcern expose :users, -> { search(User.all.includes_associated, sortable_fields) } expose :user, id: -> { params[:slug] }, scope: -> { Circle.includes_associated }, find_by: :slug diff --git a/app/frontend/Components/Section/Section.css.ts b/app/frontend/Components/Section/Section.css.ts new file mode 100644 index 0000000..e3cc4f1 --- /dev/null +++ b/app/frontend/Components/Section/Section.css.ts @@ -0,0 +1,20 @@ +import { vars, theme } from '@/lib/theme' +import { rem } from '@mantine/core' +import { css } from '@linaria/core' + +export const section = css` + ${vars.lightSelector} { + background-color: ${vars.colors.white}; + } + ${vars.darkSelector} { + background-color: ${vars.colors.gray[9]}; + } + + box-shadow: ${vars.shadows.xs}; + padding: 1rem 0.75rem; + border-top: 2px solid ${vars.colors.primaryColors.filled}; + + & + & { + margin-top: ${rem(10)}; + } +` diff --git a/app/frontend/Components/Section/Section.module.css b/app/frontend/Components/Section/Section.module.css deleted file mode 100644 index 9e93018..0000000 --- a/app/frontend/Components/Section/Section.module.css +++ /dev/null @@ -1,9 +0,0 @@ -root { - /* backgroundColor: theme.other.colorSchemeOption(theme.white, theme.colors.gray[9]), */ - /* boxShadow: theme.shadows.xs, */ - padding: '1rem 0.75rem'; - - & + & { - marginTop: 10, - } -} diff --git a/app/frontend/Components/Section/index.tsx b/app/frontend/Components/Section/index.tsx index 04705ed..2c8a355 100644 --- a/app/frontend/Components/Section/index.tsx +++ b/app/frontend/Components/Section/index.tsx @@ -1,7 +1,8 @@ import React from 'react' import { Box, ElementProps, type BoxProps } from '@mantine/core' + import cx from 'clsx' -import classes from './Section.module.css' +import * as classes from './Section.css' interface ISectionProps extends BoxProps, ElementProps<'section'> { fullHeight?: boolean @@ -11,7 +12,7 @@ const Section = ({ children, fullHeight = false, className, ...props }: ISection return ( { children } diff --git a/app/frontend/Pages/Error/index.tsx b/app/frontend/Pages/Error/index.tsx new file mode 100644 index 0000000..417c51c --- /dev/null +++ b/app/frontend/Pages/Error/index.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +interface ErrorProps { + status: any +} + +const Error = ({ status }: ErrorProps) => { + return ( + <> +
Error
+
{ status }
+ + ) +} + +export default Error diff --git a/app/frontend/Pages/Screens/Components/Control/index.tsx b/app/frontend/Pages/Screens/Components/Control/index.tsx index bee4a66..4448077 100644 --- a/app/frontend/Pages/Screens/Components/Control/index.tsx +++ b/app/frontend/Pages/Screens/Components/Control/index.tsx @@ -32,7 +32,7 @@ const Control = forwardRef(( ref, ) => { const sharedProps = { - className: cx(className, { [classes.editControl]: edit }), + className: cx(className), ref, } diff --git a/app/frontend/types/routes.d.ts b/app/frontend/types/routes.d.ts index bf29b97..d4db57b 100644 --- a/app/frontend/types/routes.d.ts +++ b/app/frontend/types/routes.d.ts @@ -468,31 +468,31 @@ export const newProtocol: (( /** * Generates rails route to - * /servers/new(.:format) + * /screens/new(.:format) * @param {object | undefined} options * @returns {string} route path */ -export const newServer: (( +export const newScreen: (( options?: {format?: OptionalRouteParameter} & RouteOptions ) => string) & RouteHelperExtras; /** * Generates rails route to - * /users/new(.:format) + * /servers/new(.:format) * @param {object | undefined} options * @returns {string} route path */ -export const newUser: (( +export const newServer: (( options?: {format?: OptionalRouteParameter} & RouteOptions ) => string) & RouteHelperExtras; /** * Generates rails route to - * /users/confirmation/new(.:format) + * /users/new(.:format) * @param {object | undefined} options * @returns {string} route path */ -export const newUserConfirmation: (( +export const newUser: (( options?: {format?: OptionalRouteParameter} & RouteOptions ) => string) & RouteHelperExtras; @@ -636,16 +636,6 @@ export const user: (( options?: {format?: OptionalRouteParameter} & RouteOptions ) => string) & RouteHelperExtras; -/** - * Generates rails route to - * /users/confirmation(.:format) - * @param {object | undefined} options - * @returns {string} route path - */ -export const userConfirmation: (( - options?: {format?: OptionalRouteParameter} & RouteOptions -) => string) & RouteHelperExtras; - /** * Generates rails route to * /users/password(.:format) diff --git a/app/frontend/types/routes.js b/app/frontend/types/routes.js index 07547ff..aa046fa 100644 --- a/app/frontend/types/routes.js +++ b/app/frontend/types/routes.js @@ -831,27 +831,27 @@ export const newProtocol = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6 /** * Generates rails route to - * /servers/new(.:format) + * /screens/new(.:format) * @param {object | undefined} options * @returns {string} route path */ -export const newServer = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"servers"],[2,[7,"/"],[2,[6,"new"],[1,[2,[8,"."],[3,"format"]]]]]]]); +export const newScreen = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"screens"],[2,[7,"/"],[2,[6,"new"],[1,[2,[8,"."],[3,"format"]]]]]]]); /** * Generates rails route to - * /users/new(.:format) + * /servers/new(.:format) * @param {object | undefined} options * @returns {string} route path */ -export const newUser = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"users"],[2,[7,"/"],[2,[6,"new"],[1,[2,[8,"."],[3,"format"]]]]]]]); +export const newServer = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"servers"],[2,[7,"/"],[2,[6,"new"],[1,[2,[8,"."],[3,"format"]]]]]]]); /** * Generates rails route to - * /users/confirmation/new(.:format) + * /users/new(.:format) * @param {object | undefined} options * @returns {string} route path */ -export const newUserConfirmation = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"users"],[2,[7,"/"],[2,[6,"confirmation"],[2,[7,"/"],[2,[6,"new"],[1,[2,[8,"."],[3,"format"]]]]]]]]]); +export const newUser = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"users"],[2,[7,"/"],[2,[6,"new"],[1,[2,[8,"."],[3,"format"]]]]]]]); /** * Generates rails route to @@ -962,14 +962,6 @@ export const updateRailsDiskService = /*#__PURE__*/ __jsr.r({"encoded_token":{"r */ export const user = /*#__PURE__*/ __jsr.r({"id":{"r":true},"format":{}}, [2,[7,"/"],[2,[6,"users"],[2,[7,"/"],[2,[3,"id"],[1,[2,[8,"."],[3,"format"]]]]]]]); -/** - * Generates rails route to - * /users/confirmation(.:format) - * @param {object | undefined} options - * @returns {string} route path - */ -export const userConfirmation = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"users"],[2,[7,"/"],[2,[6,"confirmation"],[1,[2,[8,"."],[3,"format"]]]]]]]); - /** * Generates rails route to * /users/password(.:format) diff --git a/app/lib/tasks/annotate.rb b/app/lib/tasks/annotate.rb deleted file mode 100644 index e69de29..0000000 diff --git a/app/models/screen.rb b/app/models/screen.rb index b0c170b..fa7d1e5 100644 --- a/app/models/screen.rb +++ b/app/models/screen.rb @@ -35,6 +35,8 @@ class Screen < ApplicationRecord scope :includes_associated, -> { includes([:controls]) } + validates :title, format: { without: /new/ } + accepts_nested_attributes_for :controls, reject_if: ->(attributes) { attributes['title'].blank? }, allow_destroy: true private @@ -43,6 +45,6 @@ def set_screen_order return unless self.order.nil? last_screen = Screen.order(:order).last - self.order = last_screen.order + 1 + self.order = last_screen.nil? ? 1 : last_screen.order + 1 end end diff --git a/app/models/user.rb b/app/models/user.rb index d180a43..e6d21d3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -52,8 +52,8 @@ class User < ApplicationRecord resourcify rolify - # :omniauthable, :timeoutable - devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :confirmable, :lockable, :trackable + # :omniauthable, :timeoutable, :confirmable + devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :lockable, :trackable scope :includes_associated, -> { includes([:circles]) } diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index fa3a150..4c950e6 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -52,6 +52,8 @@ def destroy? private def standard_auth(_action) - user.has_role?(:super_admin) + return true if user&.has_role?(:super_admin) + + !user.nil? end end diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint index 67ef493..2352ac7 100755 --- a/bin/docker-entrypoint +++ b/bin/docker-entrypoint @@ -1,8 +1,17 @@ #!/bin/bash -e -# If running the rails server then create or migrate existing database -if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then - ./bin/rails db:prepare +# Check if master.key exists +if [ ! -f /osc/config/secrets/master.key ]; then + echo "Generating master.key..." + # Run the rails credentials:edit command in non-interactive mode + EDITOR="echo" rails credentials:edit fi +rm -f tmp/pids/server.pid + +/osc/bin/rails db:prepare +/osc/bin/rails db:seed + +RACK_ENV="production" RAILS_ENV="production" NODE_ENV="production" /osc/bin/rails server + exec "${@}" diff --git a/config/environments/production.rb b/config/environments/production.rb index 5b23a09..3171c94 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -27,7 +27,7 @@ # config.assets.css_compressor = :sass # Do not fall back to assets pipeline if a precompiled asset is missed. - config.assets.compile = false + # config.assets.compile = false # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.asset_host = "http://assets.example.com" diff --git a/config/routes.rb b/config/routes.rb index d59ccae..b000d55 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -41,7 +41,7 @@ resources :users resources :servers, param: :slug get "screens/edit", to: "screens#edit", as: "edit_screens" - resources :screens, param: :slug, except: [:new] + resources :screens, param: :slug resources :protocols, param: :slug resources :commands, param: :slug resources :controls, only: [:create, :update, :destroy] diff --git a/config/secrets/credentials.yml.enc b/config/secrets/credentials.yml.enc index 1546b77..62c40c0 100644 --- a/config/secrets/credentials.yml.enc +++ b/config/secrets/credentials.yml.enc @@ -1 +1 @@ -xHhAOBZLKEaTJ/9qV9XhMqoBGlI7ImpGAEQhUTc1VJ9kgcp8K3H50oFMew3XPO4WNp30MMAy3xRQ4d2/xLG8PDUZ9dINxOae+lCro/vbJPNe3eYkVHAB/2O0iSeFSrr+Cg2D/NsM0cWy4X0H/E7+b0xNah/NvBokM51/OUOGa2q6c7621WzOHz7ODElpVeNkF3UrUHnbFfKCstATj4sjkV9HYx3iDoMmANITpvG/Z+To75zBacVqGJ59+G3bsdsnW61FuTdIsLMElgzgZY1FKzJMnDG8VA6QeBG2YzPnzgV+07RzwTFZ3PbsFi7m134SOZzoX6DlQX+zVtUM8d6qO465uLM3VPllTLgb8sy4/vdElolna2rgMsiXsd/P47UJMAwbdfPgVG9sWJ+uiUhHEXdswPd3LchffncH--7YUaJqXSCfgaa9GR--iy2s+hie4ej5vbzXddVObw== \ No newline at end of file +TXuAMWs7AfNfRonXDEUv++Ed24cTyGBwQEb85xbEjPVl+yqCv9OZ9j0F46vxnd1vXo5kG3Pr8PNo5xUx9hkLZh6JNCFRkpSgOzt5zDPrzW5Hg7C987F+BWU2dhJ9KCwP7+qWTE3BO/Z/BT7ekGFzyuu48oVDlOR1Z0fA4uFBwWl30Ihh97Zcp9nn78cJYvGCqGruJF8Lzc+N+PWXEG8Fl53MzfYOuLKOyqOx7H0LbIKJ2QRNRt66N5qEcE2WXMrhEMEiZjYFoaOdceGPYYqByeEBodiQr91y9FlkVDqhqKPlZb4pvrcZhbxSRkLIxgSROUZjaw7V0n09CyUgfHRyHAEnxJpQ0ZvMTrKI3YDFYFS/0Y1J/1KohdlzmeGTHLsGshvXl6RzTnie9nGoF8pwaGB2FjPq--1kPIShbOUb8jaR+W--1ral2EJGXvcmtzxx4sqm7A== \ No newline at end of file diff --git a/db/seeds/01_required.rb b/db/seeds/01_required.rb index e69de29..9045720 100644 --- a/db/seeds/01_required.rb +++ b/db/seeds/01_required.rb @@ -0,0 +1,3 @@ +if Screen.count === 0 + Screen.create title: "Main" +end diff --git a/docker_copy_files.sh b/docker_copy_files.sh new file mode 100755 index 0000000..7b705d6 --- /dev/null +++ b/docker_copy_files.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +source_paths=( + ./yarn + ./app + ./bin + ./config + ./db + ./lib + ./public + ./ruby-version + ./.yarnrc.yml + ./config.ru + ./Gemfile + ./Gemfile.lock + ./package.json + ./postcss.config.mjs + ./Rakefile + ./static.json + ./tsconfig.json + ./vite.config.ts + ./yarn.lock +) + +destination_dir=/osc/ + +cp "${source_paths[@]}" "$destination_dir" + +mkdir ./log +mkdir ./tmp + +rm -f /osc/config/secrets/master.key +rm -f /osc/config/secrets/credentials.yml.enc + +exit 0 diff --git a/lib/custom_failure.rb b/lib/custom_failure.rb index f1e594b..9d8b1fd 100644 --- a/lib/custom_failure.rb +++ b/lib/custom_failure.rb @@ -20,6 +20,9 @@ def respond_to_failure_types # Account with unconfirmed email elsif message == :unconfirmed redirect_to new_user_confirmation_path({ email: params[:user][:email] }) + elsif message == :unauthenticated + self.headers['x-inertia'] = true + redirect_to new_user_session_path end end diff --git a/vite.config.ts b/vite.config.ts index a1db2ec..14aa671 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -42,6 +42,7 @@ const config = defineConfig({ strict: false, }, }, + mode: process.env.NODE_ENV || 'development', }) export default config