add ability to unlink emails (#698)

This commit is contained in:
Arca Ege Cengiz 2025-12-09 23:22:44 +00:00 committed by GitHub
parent 4aa7384e9c
commit 385bea56f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 64 additions and 5 deletions

View file

@ -172,6 +172,40 @@ class SessionsController < ApplicationController
redirect_to my_settings_path, alert: "Failed to add email: #{e.record.errors.full_messages.join(', ')}"
end
def unlink_email
unless current_user
redirect_to root_path, alert: "Please sign in first to unlink an email"
return
end
email = params[:email].downcase
email_record = current_user.email_addresses.find_by(
email: email
)
unless email_record
redirect_to my_settings_path, alert: "Email must exist to be unlinked"
return
end
unless current_user.can_delete_email_address?(email_record)
redirect_to my_settings_path, alert: "Email must be registered for signing in to unlink"
return
end
email_verification_request = current_user.email_verification_requests.find_by(
email: email
)
email_record.destroy!
email_verification_request.destroy
redirect_to my_settings_path, notice: "Email unlinked!"
rescue ActiveRecord::RecordNotDestroyed => e
redirect_to my_settings_path, alert: "Failed to unlink email: #{e.record.errors.full_messages.join(', ')}"
end
def token
verification_request = EmailVerificationRequest.valid.find_by(token: params[:token])

View file

@ -15,6 +15,11 @@ class EmailAddress < ApplicationRecord
before_validation :downcase_email
def can_unlink?
# only allow unlinking if signin email
self.source_signing_in?
end
private
def downcase_email

View file

@ -153,6 +153,15 @@ class User < ApplicationRecord
last_audit.created_at <= 365.days.ago
end
def can_delete_emails?
# don't let user delete emails if email count is <= 1
email_addresses.size > 1
end
def can_delete_email_address?(email)
email.can_unlink? && can_delete_emails?
end
if Rails.env.development?
def self.slow_find_by_email(email)
# This is an n+1 query, but provided for developer convenience

View file

@ -245,11 +245,21 @@
<% if @user.email_addresses.any? %>
<div class="space-y-2">
<% @user.email_addresses.each do |email| %>
<div class="flex items-center gap-2 p-2 bg-gray-800 border border-gray-600 rounded">
<span class="text-gray-300 text-sm"><%= email.email %></span>
<span class="text-xs px-2 py-1 bg-gray-700 text-gray-200 rounded">
<%= email.source&.humanize || "Unknown" %>
</span>
<div class="flex gap-2 items-center">
<div class="flex items-center gap-2 p-2 bg-gray-800 border border-gray-600 rounded grow">
<span class="text-gray-300 text-sm"><%= email.email %></span>
<span class="text-xs px-2 py-1 bg-gray-700 text-gray-200 rounded">
<%= email.source&.humanize || "Unknown" %>
</span>
</div>
<% if @user.can_delete_email_address?(email) %>
<%= form_with url: unlink_email_auth_path,
method: :delete,
class: "space-y-4" do |f| %>
<%= f.hidden_field :email, value: email.email %>
<%= f.submit "Unlink!", class: "w-full px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %>
<% end %>
<% end %>
</div>
<% end %>
</div>

View file

@ -89,6 +89,7 @@ Rails.application.routes.draw do
delete "/auth/github/unlink", to: "sessions#github_unlink", as: :github_unlink
post "/auth/email", to: "sessions#email", as: :email_auth
post "/auth/email/add", to: "sessions#add_email", as: :add_email_auth
delete "/auth/email/unlink", to: "sessions#unlink_email", as: :unlink_email_auth
get "/auth/token/:token", to: "sessions#token", as: :auth_token
get "/auth/close_window", to: "sessions#close_window", as: :close_window
delete "signout", to: "sessions#destroy", as: "signout"