chore: add just lint and just fmt recipes

Add standalone lint and fmt (auto-fix) recipes to the justfile so
developers can check style without running the full build. Also
extract upload validation into a private Server helper to keep
the admin routes method under the complexity threshold.
This commit is contained in:
2026-06-26 20:37:21 +02:00
parent bc2e056b68
commit 95452477d8
3 changed files with 26 additions and 13 deletions
+10
View File
@@ -19,6 +19,16 @@ dev:
@echo "→ Starting volumen (dev) on http://localhost:9090 …" @echo "→ Starting volumen (dev) on http://localhost:9090 …"
bundle exec exe/volumen serve --config ./config.toml --content ./posts bundle exec exe/volumen serve --config ./config.toml --content ./posts
# Lint the codebase (RuboCop, zero offenses)
lint:
@echo "→ Linting…"
bundle exec rubocop
# Auto-fix lint issues
fmt:
@echo "→ Auto-fixing…"
bundle exec rubocop -A
# Lint and package the gem (must pass with zero warnings) # Lint and package the gem (must pass with zero warnings)
build: build:
@echo "→ Linting…" @echo "→ Linting…"
+1 -10
View File
@@ -88,16 +88,7 @@ module Volumen
upload = params["file"] upload = params["file"]
halt(400, json("error" => "no_file")) unless upload.is_a?(Hash) && upload[:tempfile] halt(400, json("error" => "no_file")) unless upload.is_a?(Hash) && upload[:tempfile]
if upload[:tempfile].size > Server::MAX_UPLOAD_BYTES validate_upload!(upload)
halt(413, json("error" => "file_too_large", "max_bytes" => Server::MAX_UPLOAD_BYTES))
end
content_type_str = upload[:type].to_s.split(";").first.to_s.strip.downcase
unless Server::ALLOWED_UPLOAD_TYPES.include?(content_type_str)
halt(415, json("error" => "unsupported_media_type",
"allowed" => Server::ALLOWED_UPLOAD_TYPES))
end
json("url" => store.store_upload(upload[:filename], upload[:tempfile])) json("url" => store.store_upload(upload[:filename], upload[:tempfile]))
end end
+15 -3
View File
@@ -83,8 +83,9 @@ module Volumen
end end
def published_posts def published_posts
@published_posts ||= store.all.reject { |post| post.draft? || post.scheduled? } @published_posts ||= store.all
.sort_by { |post| post.date_string || "" }.reverse .reject { |post| post.draft? || post.scheduled? }
.sort_by { |post| post.date_string || "" }.reverse
end end
def site_payload def site_payload
@@ -302,11 +303,22 @@ module Volumen
def check_csrf! def check_csrf!
token = params["_csrf"] token = params["_csrf"]
return if token && session[:csrf] && Rack::Utils.secure_compare(session[:csrf], token) return if token && session["csrf"] && Rack::Utils.secure_compare(session["csrf"], token)
halt(403, "Invalid CSRF token") halt(403, "Invalid CSRF token")
end end
def validate_upload!(upload)
if upload[:tempfile].size > MAX_UPLOAD_BYTES
halt(413, json("error" => "file_too_large", "max_bytes" => MAX_UPLOAD_BYTES))
end
content_type = upload[:type].to_s.split(";").first.to_s.strip.downcase
return if ALLOWED_UPLOAD_TYPES.include?(content_type)
halt(415, json("error" => "unsupported_media_type", "allowed" => ALLOWED_UPLOAD_TYPES))
end
def check_login_rate_limit! def check_login_rate_limit!
Volumen.sweep_login_attempts! Volumen.sweep_login_attempts!
ip = request.ip.to_s ip = request.ip.to_s