rename custom_name to username + fix audit logs

This commit is contained in:
ShyMike 2025-10-21 22:15:16 +01:00
parent 109ae988a0
commit a1bb20ab3f
9 changed files with 41 additions and 36 deletions

View file

@ -135,7 +135,7 @@ class Admin::TimelineController < Admin::BaseController
# For Stimulus: provide initial selected users with details
@initial_selected_user_objects = User.where(id: @selected_user_ids)
.select(:id, :custom_name, :slack_username, :github_username, :slack_avatar_url, :github_avatar_url)
.select(:id, :username, :slack_username, :github_username, :slack_avatar_url, :github_avatar_url)
.map { |u| { id: u.id, display_name: "#{u.display_name}", avatar_url: u.avatar_url } }
.sort_by { |u_obj| @selected_user_ids.index(u_obj[:id]) || Float::INFINITY } # Preserve order
@ -185,10 +185,10 @@ class Admin::TimelineController < Admin::BaseController
avatar_url: user_id_match.avatar_url
} ]
else
users = User.where("LOWER(custom_name) LIKE :query OR LOWER(slack_username) LIKE :query OR CAST(id AS TEXT) LIKE :query OR EXISTS (SELECT 1 FROM email_addresses WHERE email_addresses.user_id = users.id AND LOWER(email_addresses.email) LIKE :query)", query: "%#{query_term}%")
.order(Arel.sql("CASE WHEN LOWER(custom_name) = #{ActiveRecord::Base.connection.quote(query_term)} THEN 0 ELSE 1 END, username ASC")) # Prioritize exact match
users = User.where("LOWER(username) LIKE :query OR LOWER(slack_username) LIKE :query OR CAST(id AS TEXT) LIKE :query OR EXISTS (SELECT 1 FROM email_addresses WHERE email_addresses.user_id = users.id AND LOWER(email_addresses.email) LIKE :query)", query: "%#{query_term}%")
.order(Arel.sql("CASE WHEN LOWER(username) = #{ActiveRecord::Base.connection.quote(query_term)} THEN 0 ELSE 1 END, username ASC")) # Prioritize exact match
.limit(20)
.select(:id, :custom_name, :slack_username, :github_username, :slack_avatar_url, :github_avatar_url)
.select(:id, :username, :slack_username, :github_username, :slack_avatar_url, :github_avatar_url)
results = users.map do |user|
{
@ -218,7 +218,7 @@ class Admin::TimelineController < Admin::BaseController
all_ids_to_fetch.unshift(current_user.id).uniq!
users_data = User.where(id: all_ids_to_fetch)
.select(:id, :custom_name, :slack_username, :github_username, :slack_avatar_url, :github_avatar_url)
.select(:id, :username, :slack_username, :github_username, :slack_avatar_url, :github_avatar_url)
.index_by(&:id)
final_user_objects = []

View file

@ -25,7 +25,7 @@ class Admin::TrustLevelAuditLogsController < Admin::BaseController
if params[:user_search].present?
search_term = params[:user_search].strip
user_ids = User.joins(:email_addresses)
.where("LOWER(users.custom_name) LIKE ? OR LOWER(users.slack_username) LIKE ? OR LOWER(users.github_username) LIKE ? OR LOWER(email_addresses.email) LIKE ? OR CAST(users.id AS TEXT) LIKE ?",
.where("LOWER(users.username) LIKE ? OR LOWER(users.slack_username) LIKE ? OR LOWER(users.github_username) LIKE ? OR LOWER(email_addresses.email) LIKE ? OR CAST(users.id AS TEXT) LIKE ?",
"%#{search_term.downcase}%", "%#{search_term.downcase}%", "%#{search_term.downcase}%", "%#{search_term.downcase}%", "%#{search_term}%")
.pluck(:id)
@audit_logs = @audit_logs.where(user_id: user_ids)
@ -35,7 +35,7 @@ class Admin::TrustLevelAuditLogsController < Admin::BaseController
if params[:admin_search].present?
search_term = params[:admin_search].strip
admin_ids = User.joins(:email_addresses)
.where("LOWER(users.custom_name) LIKE ? OR LOWER(users.slack_username) LIKE ? OR LOWER(users.github_username) LIKE ? OR LOWER(email_addresses.email) LIKE ? OR CAST(users.id AS TEXT) LIKE ?",
.where("LOWER(users.username) LIKE ? OR LOWER(users.slack_username) LIKE ? OR LOWER(users.github_username) LIKE ? OR LOWER(email_addresses.email) LIKE ? OR CAST(users.id AS TEXT) LIKE ?",
"%#{search_term.downcase}%", "%#{search_term.downcase}%", "%#{search_term.downcase}%", "%#{search_term.downcase}%", "%#{search_term}%")
.pluck(:id)
@audit_logs = @audit_logs.where(changed_by_id: admin_ids)

View file

@ -15,7 +15,7 @@ module Api
},
creator: {
id: creator.id,
username: creator.custom_name,
username: creator.username,
display_name: creator.display_name,
admin_level: creator.admin_level
}
@ -75,7 +75,7 @@ module Api
render json: {
user: {
id: user.id,
username: user.custom_name,
username: user.username,
display_name: user.display_name,
slack_uid: user.slack_uid,
slack_username: user.slack_username,
@ -299,7 +299,7 @@ module Api
new_trust_level: log.new_trust_level,
changed_by: {
id: log.changed_by.id,
username: log.changed_by.name,
username: log.changed_by.username,
display_name: log.changed_by.display_name,
admin_level: log.changed_by.admin_level
},

View file

@ -153,7 +153,7 @@ class UsersController < ApplicationController
:timezone,
:allow_public_stats_lookup,
:default_timezone_leaderboard,
:custom_name,
:username,
)
end
end

View file

@ -2,23 +2,23 @@ class User < ApplicationRecord
include TimezoneRegions
include PublicActivity::Model
CUSTOM_NAME_MAX_LENGTH = 21 # going over 21 overflows the navbar
USERNAME_MAX_LENGTH = 21 # going over 21 overflows the navbar
has_paper_trail
after_create :create_signup_activity
before_validation :normalize_custom_name
before_validation :normalize_username
encrypts :slack_access_token, :github_access_token
validates :slack_uid, uniqueness: true, allow_nil: true
validates :github_uid, uniqueness: { conditions: -> { where.not(github_access_token: nil) } }, allow_nil: true
validates :timezone, inclusion: { in: TZInfo::Timezone.all_identifiers }, allow_nil: false
validates :country_code, inclusion: { in: ISO3166::Country.codes }, allow_nil: true
validates :custom_name,
length: { maximum: CUSTOM_NAME_MAX_LENGTH },
validates :username,
length: { maximum: USERNAME_MAX_LENGTH },
format: { with: /\A[A-Za-z0-9_-]+\z/, message: "may only include letters, numbers, '-', and '_'" },
allow_nil: true
validate :custom_name_must_be_visible
validate :username_must_be_visible
attribute :allow_public_stats_lookup, :boolean, default: true
attribute :default_timezone_leaderboard, :boolean, default: true
@ -468,7 +468,7 @@ class User < ApplicationRecord
end
def display_name
name = custom_name || slack_username || github_username
name = username || slack_username || github_username
return name if name.present?
# "zach@hackclub.com" -> "zach (email sign-up)"
@ -517,9 +517,9 @@ class User < ApplicationRecord
create_activity :first_signup, owner: self
end
def normalize_custom_name
original = custom_name
@custom_name_cleared_for_invisible = false
def normalize_username
original = username
@username_cleared_for_invisible = false
return if original.nil?
@ -527,16 +527,16 @@ class User < ApplicationRecord
stripped = cleaned.strip
if stripped.empty?
self.custom_name = nil
@custom_name_cleared_for_invisible = original.length.positive?
self.username = nil
@username_cleared_for_invisible = original.length.positive?
else
self.custom_name = stripped
self.username = stripped
end
end
def custom_name_must_be_visible
if instance_variable_defined?(:@custom_name_cleared_for_invisible) && @custom_name_cleared_for_invisible
errors.add(:custom_name, "must include visible characters")
def username_must_be_visible
if instance_variable_defined?(:@username_cleared_for_invisible) && @username_cleared_for_invisible
errors.add(:username, "must include visible characters")
end
end
end

View file

@ -73,24 +73,24 @@
<div class="p-2 bg-red-600/10 rounded">
<span class="text-2xl">🪪</span>
</div>
<h2 class="text-xl font-semibold text-white" id="user_custom_name">Display Name</h2>
<h2 class="text-xl font-semibold text-white" id="user_username">Display Name</h2>
</div>
<%= form_with model: @user,
url: @is_own_settings ? my_settings_path : settings_user_path(@user),
method: :patch, local: false,
class: "space-y-4" do |f| %>
<div>
<%= f.label :custom_name, "Custom display name", class: "block text-sm font-medium text-gray-200 mb-2" %>
<%= f.text_field :custom_name,
<%= f.label :username, "Custom display name", class: "block text-sm font-medium text-gray-200 mb-2" %>
<%= f.text_field :username,
class: "w-full px-3 py-2 bg-gray-800 border border-gray-600 rounded text-white focus:border-primary focus:ring-1 focus:ring-primary",
placeholder: "HackClubber",
maxlength: User::CUSTOM_NAME_MAX_LENGTH %>
<% if @user.errors[:custom_name].present? %>
<p class="mt-1 text-xs text-red-400"><%= @user.errors[:custom_name].to_sentence %></p>
maxlength: User::USERNAME_MAX_LENGTH %>
<% if @user.errors[:username].present? %>
<p class="mt-1 text-xs text-red-400"><%= @user.errors[:username].to_sentence %></p>
<% end %>
</div>
<p class="text-xs text-gray-400">
Choose a name to use in Hackatime. This will take priority over Slack or GitHub names when possible. Letters, numbers, "-" and "_" only, max <%= User::CUSTOM_NAME_MAX_LENGTH %> chars.
Choose a name to use in Hackatime. This will take priority over Slack or GitHub names when possible. Letters, numbers, "-" and "_" only, max <%= User::USERNAME_MAX_LENGTH %> chars.
</p>
<%= f.submit "Save Settings", class: "w-full px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %>
<% end %>

View file

@ -0,0 +1,5 @@
class RenameCustomUsername < ActiveRecord::Migration[8.0]
def change
rename_column :users, :custom_name, :username
end
end

4
db/schema.rb generated
View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_10_21_202329) do
ActiveRecord::Schema[8.0].define(version: 2025_10_21_211039) do
create_schema "pganalyze"
# These are extensions that must be enabled in order to support this database
@ -562,7 +562,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_10_21_202329) do
t.boolean "allow_public_stats_lookup", default: true, null: false
t.boolean "default_timezone_leaderboard", default: true, null: false
t.integer "admin_level", default: 0, null: false
t.string "custom_name"
t.string "username"
t.index ["github_uid", "github_access_token"], name: "index_users_on_github_uid_and_access_token"
t.index ["github_uid"], name: "index_users_on_github_uid"
t.index ["slack_uid"], name: "index_users_on_slack_uid", unique: true

View file

@ -14,7 +14,7 @@ Doorkeeper::Application.find_or_create_by(
if Rails.env.development?
# Creating test user
test_user = User.find_or_create_by(slack_uid: 'TEST123456') do |user|
user.custom_name = 'testuser'
user.username = 'testuser'
user.slack_username = 'testuser'
# Before you had user.is_admin = true, does not work, changed it to that, looks like it works but idk how to use the admin pages so pls check this, i just guess coded this, the cmd to seed the db works without errors