style(ntfy): fix bracket-spacing lint offenses

This commit is contained in:
Min Zeya Phyo
2026-07-28 02:34:26 +08:00
parent 20927eea5f
commit ac2054e45c
13 changed files with 1502 additions and 70 deletions

View File

@@ -1,6 +1,7 @@
module Admin
class BaseController < ActionController::Base
include Pagy::Backend
include AdminAuthentication
# Enable session and flash for admin controllers
# (needed because the app is in API-only mode)
@@ -9,22 +10,12 @@ module Admin
layout "admin"
before_action :require_admin
helper_method :current_admin, :logged_in?
private
def current_admin
@current_admin ||= AdminUser.find_by(id: session[:admin_id]) if session[:admin_id]
end
helper_method :current_admin
def logged_in?
current_admin.present?
end
helper_method :logged_in?
def require_admin
unless logged_in?
redirect_to admin_login_path, alert: "Please log in to continue"
end
redirect_to admin_login_path, alert: "Please log in to continue" unless logged_in?
end
end
end

View File

@@ -1,11 +1,15 @@
module Admin
class SessionsController < ActionController::Base
include AdminAuthentication
layout "admin"
# CSRF protection is enabled by default in ActionController::Base
# We need it for the create action but not for the new (GET) action
protect_from_forgery with: :exception
helper_method :current_admin, :logged_in?
def new
redirect_to admin_dashboard_path if current_admin
end
@@ -27,12 +31,5 @@ module Admin
session.delete(:admin_id)
redirect_to admin_login_path, notice: "You have been logged out"
end
private
def current_admin
@current_admin ||= AdminUser.find_by(id: session[:admin_id]) if session[:admin_id]
end
helper_method :current_admin
end
end

View File

@@ -0,0 +1,11 @@
module AdminAuthentication
extend ActiveSupport::Concern
def current_admin
@current_admin ||= AdminUser.find_by(id: session[:admin_id]) if session[:admin_id]
end
def logged_in?
current_admin.present?
end
end

View File

@@ -1,9 +1,2 @@
module AdminHelper
def current_admin
@current_admin ||= AdminUser.find_by(id: session[:admin_id]) if session[:admin_id]
end
def logged_in?
current_admin.present?
end
end

View File

@@ -1,12 +1,3 @@
module ApplicationHelper
include Pagy::Frontend
# Admin authentication helpers
def current_admin
@current_admin ||= AdminUser.find_by(id: session[:admin_id]) if session[:admin_id]
end
def logged_in?
current_admin.present?
end
end

View File

@@ -18,7 +18,7 @@ class CheckGatewayHealthJob < ApplicationJob
title: "Gateway offline",
message: "#{name} (#{device_id}) went offline — no heartbeat for 2+ minutes",
priority: 4,
tags: ["rotating_light"])
tags: [ "rotating_light" ])
end
end
end

View File

@@ -63,7 +63,7 @@ class ApiKey < ApplicationRecord
title: "API key revoked",
message: "API key '#{name}' (#{key_prefix}...) was revoked",
priority: 3,
tags: ["key", "no_entry"])
tags: [ "key", "no_entry" ])
end
# Deactivate expired keys

View File

@@ -45,7 +45,7 @@ class Gateway < ApplicationRecord
title: "Gateway online",
message: "#{name} (#{device_id}) came back online",
priority: 3,
tags: ["white_check_mark"],
tags: [ "white_check_mark" ],
click: nil)
end
end
@@ -60,7 +60,7 @@ class Gateway < ApplicationRecord
title: "Gateway offline",
message: "#{name} (#{device_id}) went offline",
priority: 4,
tags: ["rotating_light"])
tags: [ "rotating_light" ])
end
end

View File

@@ -60,7 +60,7 @@ class SmsMessage < ApplicationRecord
title: "SMS delivered",
message: "Message to #{phone_number} (#{message_id}) was delivered",
priority: 2,
tags: ["white_check_mark"])
tags: [ "white_check_mark" ])
end
# Mark message as failed
@@ -71,7 +71,7 @@ class SmsMessage < ApplicationRecord
title: "SMS failed",
message: "Message to #{phone_number} (#{message_id}) failed#{error_msg ? ": #{error_msg}" : ''}",
priority: 5,
tags: ["x", "rotating_light"])
tags: [ "x", "rotating_light" ])
end
# Increment retry counter

View File

@@ -1,22 +1,27 @@
<div class="w-full max-w-md space-y-8">
<div class="fade-up">
<div class="text-center">
<div class="mx-auto h-16 w-16 flex items-center justify-center rounded-full bg-blue-100">
<i class="fas fa-sms text-3xl text-blue-600"></i>
<div class="relative mx-auto h-20 w-20 flex items-center justify-center">
<span class="beacon-ring absolute inset-0 rounded-full border border-sky-400/50"></span>
<span class="beacon-ring delay-1 absolute inset-0 rounded-full border border-sky-400/40"></span>
<span class="beacon-ring delay-2 absolute inset-0 rounded-full border border-sky-400/30"></span>
<div class="relative flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br from-sky-400 to-sky-600 shadow-lg shadow-sky-500/40">
<i class="fas fa-sms text-2xl text-slate-950"></i>
</div>
</div>
<h2 class="mt-6 text-3xl font-bold tracking-tight text-gray-900">MySMSAPio Admin</h2>
<p class="mt-2 text-sm text-gray-600">Sign in to your admin account</p>
<h2 class="font-display mt-6 text-4xl font-extrabold tracking-tight text-white">MySMSAPio</h2>
<p class="font-mono-tech mt-2 text-[11px] uppercase tracking-[0.35em] text-sky-400/80">Admin Console</p>
</div>
<div class="mt-8 bg-white py-8 px-4 shadow-xl rounded-xl sm:px-10">
<%= form_with url: admin_login_path, method: :post, local: true, class: "space-y-6" do |f| %>
<div class="login-card fade-up d-1 mt-8 rounded-2xl px-8 py-9 sm:px-10">
<%= form_with url: admin_login_path, method: :post, local: true, class: "space-y-5" do |f| %>
<div>
<%= label_tag :email, "Email address", class: "block text-sm font-medium text-gray-700" %>
<div class="mt-1 relative">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<i class="fas fa-envelope text-gray-400"></i>
<%= label_tag :email, "Email address", class: "font-mono-tech block text-[11px] uppercase tracking-wider text-slate-400" %>
<div class="mt-2 relative">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3.5">
<i class="fas fa-envelope text-slate-500 text-sm"></i>
</div>
<%= email_field_tag :email, params[:email],
class: "block w-full pl-10 rounded-lg border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm py-3",
class: "field-input block w-full rounded-xl pl-11 pr-3 py-3 text-sm",
placeholder: "admin@example.com",
autofocus: true,
required: true %>
@@ -24,26 +29,27 @@
</div>
<div>
<%= label_tag :password, "Password", class: "block text-sm font-medium text-gray-700" %>
<div class="mt-1 relative">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<i class="fas fa-lock text-gray-400"></i>
<%= label_tag :password, "Password", class: "font-mono-tech block text-[11px] uppercase tracking-wider text-slate-400" %>
<div class="mt-2 relative">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3.5">
<i class="fas fa-lock text-slate-500 text-sm"></i>
</div>
<%= password_field_tag :password, nil,
class: "block w-full pl-10 rounded-lg border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm py-3",
placeholder: "Enter your password",
class: "field-input block w-full rounded-xl pl-11 pr-3 py-3 text-sm",
placeholder: "••••••••••••",
required: true %>
</div>
</div>
<div>
<div class="pt-2">
<%= submit_tag "Sign in",
class: "flex w-full justify-center rounded-lg bg-blue-600 px-4 py-3 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 transition-all duration-200" %>
class: "btn-accent flex w-full justify-center rounded-xl px-4 py-3.5 text-sm font-semibold text-slate-950" %>
</div>
<% end %>
</div>
<div class="text-center text-xs text-gray-500">
<i class="fas fa-shield-alt"></i> Secure Admin Access
<div class="fade-up d-2 mt-7 flex items-center justify-center gap-2 font-mono-tech text-[10px] uppercase tracking-[0.3em] text-slate-500">
<i class="fas fa-shield-halved text-sky-500/70"></i>
Secure · Encrypted · Local
</div>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
email: MyString
password_digest: MyString
name: MyString
email: one@example.com
password_digest: <%= BCrypt::Password.create("password123") %>
name: Admin One
last_login_at: 2025-10-20 10:51:35
two:
email: MyString
password_digest: MyString
name: MyString
email: two@example.com
password_digest: <%= BCrypt::Password.create("password123") %>
name: Admin Two
last_login_at: 2025-10-20 10:51:35

View File

@@ -0,0 +1,48 @@
require "test_helper"
class AdminSessionsFlowTest < ActionDispatch::IntegrationTest
def setup
@admin = AdminUser.create!(name: "Site Admin", email: "admin@example.com", password: "supersecret123")
end
test "login page renders the sign-in form" do
get admin_login_path
assert_response :success
assert_match "MySMSAPio", response.body
assert_match "Sign in", response.body
end
test "login page displays the auth error message on failed login" do
post admin_login_path, params: { email: "admin@example.com", password: "wrong-password" }
assert_response :unprocessable_entity
# The critical regression check: the alert must be present in the rendered HTML
assert_match "Invalid email or password", response.body
end
test "successful login redirects to the dashboard and shows welcome notice" do
post admin_login_path, params: { email: "admin@example.com", password: "supersecret123" }
assert_redirected_to admin_dashboard_path
follow_redirect!
assert_match "Welcome back", response.body
end
test "login is case-insensitive for email" do
post admin_login_path, params: { email: "ADMIN@example.com", password: "supersecret123" }
assert_redirected_to admin_dashboard_path
end
test "logging out clears the session and shows notice on the login page" do
post admin_login_path, params: { email: "admin@example.com", password: "supersecret123" }
delete admin_logout_path
assert_redirected_to admin_login_path
follow_redirect!
assert_match "logged out", response.body
end
test "protected admin page redirects to login with an alert" do
get admin_dashboard_path
assert_redirected_to admin_login_path
follow_redirect!
assert_match "Please log in to continue", response.body
end
end