Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions app/controllers/admin/timeline_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def show

# 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

Expand Down Expand Up @@ -185,10 +185,10 @@ def search_users
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|
{
Expand Down Expand Up @@ -218,7 +218,7 @@ def leaderboard_users
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 = []
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/admin/trust_level_audit_logs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def index
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)
Expand All @@ -35,7 +35,7 @@ def index
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)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/api/admin/v1/admin_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def check
},
creator: {
id: creator.id,
username: creator.custom_name,
username: creator.username,
display_name: creator.display_name,
admin_level: creator.admin_level
}
Expand Down Expand Up @@ -75,7 +75,7 @@ def user_info
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,
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def user_params
:timezone,
:allow_public_stats_lookup,
:default_timezone_leaderboard,
:custom_name,
:username,
)
end
end
30 changes: 15 additions & 15 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -468,7 +468,7 @@ def avatar_url
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)"
Expand Down Expand Up @@ -517,26 +517,26 @@ def create_signup_activity
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?

cleaned = original.gsub(/\p{Cf}/, "")
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
14 changes: 7 additions & 7 deletions app/views/users/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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 %>
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20251021211039_rename_custom_username.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class RenameCustomUsername < ActiveRecord::Migration[8.0]
def change
rename_column :users, :custom_name, :username
end
end
4 changes: 2 additions & 2 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
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
Expand Down