This commit is contained in:
24c02 2026-01-30 13:38:25 -05:00
parent 87ca70ba60
commit bd69e16672
31 changed files with 57 additions and 59 deletions

View file

@ -53,7 +53,7 @@ end
gem "jb"
gem "pry-rails", group: :development
gem "awesome_print"
gem "dotenv-rails", groups: [:development, :test]
gem "dotenv-rails", groups: [ :development, :test ]
gem "hashid-rails"
gem "vite_rails"
gem "phlex-rails"

View file

@ -100,7 +100,7 @@ class Components::Admin::Users::Show < Components::Base
end
# Progress bar
div(style: "background: var(--bgColor-muted); border-radius: 3px; height: 8px; overflow: hidden;") do
div(style: "background: #{progress_bar_color(usage[:percentage_used])}; height: 100%; width: #{[usage[:percentage_used], 100].min}%;")
div(style: "background: #{progress_bar_color(usage[:percentage_used])}; height: 100%; width: #{[ usage[:percentage_used], 100 ].min}%;")
end
end

View file

@ -25,7 +25,6 @@ class Components::HeaderBar < Components::Base
return unless signed_in?
div(style: "display: flex; align-items: center; gap: 0.5rem;") do
render(Primer::Alpha::ActionMenu.new(anchor_align: :end)) do |menu|
menu.with_show_button(scheme: :invisible) do |btn|
btn.with_leading_visual_icon(icon: impersonating? ? :eye : :person)

View file

@ -115,7 +115,7 @@ class Components::StaticPages::Home < Components::StaticPages::Base
end
# Progress bar
div(style: "background: var(--bgColor-muted); border-radius: 3px; height: 6px; overflow: hidden;") do
div(style: "background: #{progress_color}; height: 100%; width: #{[percentage, 100].min}%;")
div(style: "background: #{progress_color}; height: 100%; width: #{[ percentage, 100 ].min}%;")
end
end
end

View file

@ -11,4 +11,4 @@ module Admin
) unless current_user&.is_admin?
end
end
end
end

View file

@ -50,4 +50,4 @@ module API
end
end
end
end
end

View file

@ -3,7 +3,7 @@
module API
module V4
class UploadsController < ApplicationController
before_action :check_quota, only: [:create, :create_from_url]
before_action :check_quota, only: [ :create, :create_from_url ]
# POST /api/v4/upload
def create
@ -75,7 +75,7 @@ module API
unless quota_service.can_upload?(file_size)
usage = quota_service.current_usage
render json: quota_error_json(usage), status: :payment_required
return
nil
end
end
# For URL uploads, quota is checked after download in create_from_url

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
class APIKeysController < ApplicationController
before_action :set_api_key, only: [:destroy]
before_action :set_api_key, only: [ :destroy ]
def index
@api_keys = current_user.api_keys.active.recent

View file

@ -1,5 +1,5 @@
class StaticPagesController < ApplicationController
skip_before_action :require_authentication!, only: [:home]
skip_before_action :require_authentication!, only: [ :home ]
def home
@flavor_text = FlavorTextService.new(user: current_user).generate

View file

@ -1,8 +1,8 @@
# frozen_string_literal: true
class UploadsController < ApplicationController
before_action :set_upload, only: [:destroy]
before_action :check_quota, only: [:create]
before_action :set_upload, only: [ :destroy ]
before_action :check_quota, only: [ :create ]
def index
@uploads = current_user.uploads.includes(:blob).recent
@ -67,7 +67,7 @@ class UploadsController < ApplicationController
unless quota_service.can_upload?(file_size)
usage = quota_service.current_usage
redirect_to uploads_path, alert: "Uploading this file would exceed your storage quota. You're using #{ActiveSupport::NumberHelper.number_to_human_size(usage[:storage_used])} of #{ActiveSupport::NumberHelper.number_to_human_size(usage[:storage_limit])}."
return
nil
end
end

View file

@ -6,7 +6,7 @@ class ApplicationRecord < ActiveRecord::Base
private
def generate_uuid_v7
return if self.class.attribute_types['id'].type != :uuid
return if self.class.attribute_types["id"].type != :uuid
self.id ||= SecureRandom.uuid_v7
end
end

View file

@ -53,10 +53,10 @@ class DocPage
parts = content.split("---", 3)
if parts.length >= 3
frontmatter = YAML.safe_load(parts[1]) || {}
return [frontmatter, parts[2].strip]
return [ frontmatter, parts[2].strip ]
end
end
[{}, content]
[ {}, content ]
end
def render_markdown(content)

View file

@ -4,8 +4,8 @@ class Quota
ALL_POLICIES = [
Policy[:unverified, 10.megabytes, 50.megabytes],
Policy[:verified, 50.megabytes, 50.gigabytes],
Policy[:functionally_unlimited, 200.megabytes, 300.gigabytes],
Policy[:functionally_unlimited, 200.megabytes, 300.gigabytes]
].index_by &:slug
def self.policy(slug) = ALL_POLICIES.fetch slug
end
end

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'open-uri'
require "open-uri"
class Upload < ApplicationRecord
include PgSearch::Model
@ -8,7 +8,7 @@ class Upload < ApplicationRecord
# UUID v7 primary key (automatic via migration)
belongs_to :user
belongs_to :blob, class_name: 'ActiveStorage::Blob'
belongs_to :blob, class_name: "ActiveStorage::Blob"
after_destroy :purge_blob
@ -25,10 +25,10 @@ class Upload < ApplicationRecord
}
pg_search_scope :search,
against: [:original_url],
against: [ :original_url ],
associated_against: {
blob: :filename,
user: [:email, :name]
user: [ :email, :name ]
},
using: { tsearch: { prefix: true } }
@ -38,19 +38,19 @@ class Upload < ApplicationRecord
# Provenance enum
enum :provenance, {
slack: 'slack',
web: 'web',
api: 'api',
rescued: 'rescued'
slack: "slack",
web: "web",
api: "api",
rescued: "rescued"
}, validate: true
validates :provenance, presence: true
scope :recent, -> { order(created_at: :desc) }
scope :by_user, ->(user) { where(user: user) }
scope :today, -> { where('created_at >= ?', Time.zone.now.beginning_of_day) }
scope :this_week, -> { where('created_at >= ?', Time.zone.now.beginning_of_week) }
scope :this_month, -> { where('created_at >= ?', Time.zone.now.beginning_of_month) }
scope :today, -> { where("created_at >= ?", Time.zone.now.beginning_of_day) }
scope :this_week, -> { where("created_at >= ?", Time.zone.now.beginning_of_week) }
scope :this_month, -> { where("created_at >= ?", Time.zone.now.beginning_of_month) }
def human_file_size
ActiveSupport::NumberHelper.number_to_human_size(byte_size)
@ -61,7 +61,7 @@ class Upload < ApplicationRecord
Rails.application.routes.url_helpers.external_upload_url(
id:,
filename:,
host: ENV['CDN_HOST'] || 'cdn.hackclub.com'
host: ENV["CDN_HOST"] || "cdn.hackclub.com"
)
end

View file

@ -7,7 +7,7 @@ class User < ApplicationRecord
def to_param = public_id
pg_search_scope :search,
against: [:email, :name, :slack_id],
against: [ :email, :name, :slack_id ],
using: { tsearch: { prefix: true } }
scope :admins, -> { where(is_admin: true) }
@ -16,7 +16,7 @@ class User < ApplicationRecord
encrypts :hca_access_token
has_many :uploads, dependent: :destroy
has_many :api_keys, dependent: :destroy, class_name: 'APIKey'
has_many :api_keys, dependent: :destroy, class_name: "APIKey"
def self.find_or_create_from_omniauth(auth)
hca_id = auth.uid
@ -53,7 +53,7 @@ class User < ApplicationRecord
end
def total_storage_bytes
uploads.joins(:blob).sum('active_storage_blobs.byte_size')
uploads.joins(:blob).sum("active_storage_blobs.byte_size")
end
def total_storage_gb

View file

@ -26,7 +26,7 @@ class CDNStatsService
used = usage[:storage_used]
max = usage[:storage_limit]
percentage = usage[:percentage_used]
available = [max - used, 0].max
available = [ max - used, 0 ].max
{
total_files: user.total_files,
@ -50,7 +50,7 @@ class CDNStatsService
def self.calculate_global_stats
total_files = Upload.count
total_storage_bytes = Upload.joins(:blob).sum('active_storage_blobs.byte_size')
total_storage_bytes = Upload.joins(:blob).sum("active_storage_blobs.byte_size")
total_users = User.joins(:uploads).distinct.count
{

View file

@ -167,7 +167,7 @@ class FlavorTextService
"low-sodium edition",
'we put the ":3" in "S3"!',
"do not adjust your monitor.",
"only #{@random.rand(5..50)} missing #{["file", "files"].sample(random: @random)}!",
"only #{@random.rand(5..50)} missing #{[ "file", "files" ].sample(random: @random)}!",
"why are you reading these",
"go outside",
"posture check!",
@ -229,7 +229,7 @@ class FlavorTextService
"100% bug-free* *no it's not",
"who let me cook",
"cooked (derogatory)",
"this seemed like a good idea at the time",
"this seemed like a good idea at the time"
]
end
@ -238,4 +238,4 @@ class FlavorTextService
def sample
flavor_texts.sample(random: @random)
end
end
end

View file

@ -8,7 +8,6 @@ Bundler.require(*Rails.groups)
module CDN
class Application < Rails::Application
require "view_component"
require "primer/view_components"

View file

@ -34,7 +34,7 @@ Rails.application.configure do
# config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }
# Log to STDOUT with the current request id as a default log tag.
config.log_tags = [:request_id]
config.log_tags = [ :request_id ]
config.logger = ActiveSupport::TaggedLogging.logger(STDOUT)
# Change to "debug" to log everything (including potentially personally-identifiable information!)
@ -77,7 +77,7 @@ Rails.application.configure do
config.active_record.dump_schema_after_migration = false
# Only use :id for inspections in production.
config.active_record.attributes_for_inspect = [:id]
config.active_record.attributes_for_inspect = [ :id ]
# Enable DNS rebinding protection and other `Host` header attacks.
# config.hosts = [

View file

@ -1,3 +1,3 @@
# frozen_string_literal: true
BlindIndex.master_key = ENV.fetch('BLIND_INDEX_MASTER_KEY')
BlindIndex.master_key = ENV.fetch("BLIND_INDEX_MASTER_KEY")

View file

@ -11,10 +11,10 @@
# policy.img_src :self, :https, :data
# policy.object_src :none
# policy.script_src :self, :https
# Allow @vite/client to hot reload javascript changes in development
# Allow @vite/client to hot reload javascript changes in development
# policy.script_src *policy.script_src, :unsafe_eval, "http://#{ ViteRuby.config.host_with_port }" if Rails.env.development?
# You may need to enable this in production as well depending on your setup.
# You may need to enable this in production as well depending on your setup.
# policy.script_src *policy.script_src, :blob if Rails.env.test?
# Allow @vite/client to hot reload javascript changes in development
@ -24,7 +24,7 @@
# policy.script_src *policy.script_src, :blob if Rails.env.test?
# policy.style_src :self, :https
# Allow @vite/client to hot reload style changes in development
# Allow @vite/client to hot reload style changes in development
# policy.style_src *policy.style_src, :unsafe_inline if Rails.env.development?
# Allow @vite/client to hot reload style changes in development

View file

@ -4,5 +4,5 @@
# Use this to limit dissemination of sensitive information.
# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
Rails.application.config.filter_parameters += [
:passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc,
:passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc
]

View file

@ -1,3 +1,3 @@
# frozen_string_literal: true
Lockbox.master_key = ENV.fetch('LOCKBOX_MASTER_KEY')
Lockbox.master_key = ENV.fetch("LOCKBOX_MASTER_KEY")

View file

@ -5,5 +5,5 @@ Rails.application.config.middleware.use OmniAuth::Builder do
scope: "openid email name slack_id verification_status",
staging: !Rails.env.production?
end
OmniAuth.config.allowed_request_methods = [:post]
OmniAuth.config.allowed_request_methods = [ :post ]
OmniAuth.config.request_validation_phase = OmniAuth::AuthenticityTokenProtection.new(key: :_csrf_token)

View file

@ -1,6 +1,6 @@
Sentry.init do |config|
config.dsn = ENV["SENTRY_DSN"]
config.breadcrumbs_logger = [:active_support_logger, :http_logger]
config.breadcrumbs_logger = [ :active_support_logger, :http_logger ]
config.traces_sample_rate = 0.1
config.send_default_pii = false
config.enabled_environments = %w[production staging]

View file

@ -1,13 +1,13 @@
Rails.application.routes.draw do
namespace :admin do
get "search", to: "search#index"
resources :users, only: [:show, :destroy] do
resources :users, only: [ :show, :destroy ] do
member do
patch "set_quota"
end
end
resources :uploads, only: [:destroy]
resources :api_keys, only: [:destroy]
resources :uploads, only: [ :destroy ]
resources :api_keys, only: [ :destroy ]
end
delete "/logout", to: "sessions#destroy", as: :logout
@ -17,9 +17,9 @@ Rails.application.routes.draw do
get "/auth/hack_club/callback", to: "sessions#create"
get "/auth/failure", to: "sessions#failure"
resources :uploads, only: [:index, :create, :destroy]
resources :uploads, only: [ :index, :create, :destroy ]
resources :api_keys, only: [:index, :create, :destroy]
resources :api_keys, only: [ :index, :create, :destroy ]
namespace :api do
namespace :v4 do

View file

@ -12,7 +12,7 @@ class CreateUploads < ActiveRecord::Migration[8.0]
t.timestamps
t.index [:user_id, :created_at]
t.index [ :user_id, :created_at ]
t.index :created_at
t.index :provenance
end

View file

@ -10,7 +10,7 @@ class CreateAPIKeys < ActiveRecord::Migration[8.0]
t.timestamps
t.index :token_bidx, unique: true
t.index [:user_id, :revoked]
t.index [ :user_id, :revoked ]
end
end
end

View file

@ -15,7 +15,7 @@ if Rails.env.development?
name: 'Dev User'
)
provenances = [:web, :api, :slack, :rescued]
provenances = [ :web, :api, :slack, :rescued ]
10.times do |i|
# Create dummy file content

View file

@ -1,5 +1,5 @@
require "test_helper"
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
driven_by :selenium, using: :headless_chrome, screen_size: [ 1400, 1400 ]
end

View file

@ -82,7 +82,7 @@ class API::V4::UploadsControllerTest < ActionDispatch::IntegrationTest
url = "https://example.com/broken.jpg"
# Simulate an error
URI.stub :open, -> (_) { raise StandardError, "Network error" } do
URI.stub :open, ->(_) { raise StandardError, "Network error" } do
post api_v4_upload_from_url_url,
params: { url: url }.to_json,
headers: {