mirror of
https://github.com/we-promise/sure.git
synced 2026-05-24 21:14:56 +00:00
OidcIdentity#sync_user_attributes! runs on every SSO sign-in and overwrote user.first_name / user.last_name with whatever the IdP sent, because the precedence was `auth.info.* || user.*` — the IdP always won when it supplied a value. A user who edited their first name to "Adam" inside Sure had it reset to the IdP value "Ben" on the next login, while the last name only "stuck" when the IdP happened not to return a last_name (#1103). Swap the precedence to `user.* || auth.info.*` so the IdP fills only when Sure has nothing on file (first link or admin-blanked field). Edits inside Sure are then authoritative for every subsequent login. The audit copy on the OidcIdentity record itself is unchanged, so the IdP-reported name is still available for debugging. Closes #1103. Co-authored-by: plind-junior <plind-junior@users.noreply.github.com>
118 lines
3.5 KiB
Ruby
118 lines
3.5 KiB
Ruby
require "test_helper"
|
|
|
|
class OidcIdentityTest < ActiveSupport::TestCase
|
|
setup do
|
|
@user = users(:family_admin)
|
|
@oidc_identity = oidc_identities(:bob_google)
|
|
end
|
|
|
|
test "belongs to user" do
|
|
assert_equal @user, @oidc_identity.user
|
|
end
|
|
|
|
test "validates presence of provider" do
|
|
@oidc_identity.provider = nil
|
|
assert_not @oidc_identity.valid?
|
|
assert_includes @oidc_identity.errors[:provider], "can't be blank"
|
|
end
|
|
|
|
test "validates presence of uid" do
|
|
@oidc_identity.uid = nil
|
|
assert_not @oidc_identity.valid?
|
|
assert_includes @oidc_identity.errors[:uid], "can't be blank"
|
|
end
|
|
|
|
test "validates presence of user_id" do
|
|
@oidc_identity.user_id = nil
|
|
assert_not @oidc_identity.valid?
|
|
assert_includes @oidc_identity.errors[:user_id], "can't be blank"
|
|
end
|
|
|
|
test "validates uniqueness of uid scoped to provider" do
|
|
duplicate = OidcIdentity.new(
|
|
user: users(:family_member),
|
|
provider: @oidc_identity.provider,
|
|
uid: @oidc_identity.uid
|
|
)
|
|
|
|
assert_not duplicate.valid?
|
|
assert_includes duplicate.errors[:uid], "has already been taken"
|
|
end
|
|
|
|
test "allows same uid for different providers" do
|
|
different_provider = OidcIdentity.new(
|
|
user: users(:family_member),
|
|
provider: "different_provider",
|
|
uid: @oidc_identity.uid
|
|
)
|
|
|
|
assert different_provider.valid?
|
|
end
|
|
|
|
test "records authentication timestamp" do
|
|
old_timestamp = @oidc_identity.last_authenticated_at
|
|
travel_to 1.hour.from_now do
|
|
@oidc_identity.record_authentication!
|
|
assert @oidc_identity.last_authenticated_at > old_timestamp
|
|
end
|
|
end
|
|
|
|
test "sync_user_attributes! preserves user-edited first and last name" do
|
|
# Regression for #1103: every SSO login used to overwrite user.first_name
|
|
# with the IdP value, clobbering edits the user made inside Sure.
|
|
@user.update!(first_name: "Adam", last_name: "Smith")
|
|
auth = OmniAuth::AuthHash.new(
|
|
provider: @oidc_identity.provider,
|
|
uid: @oidc_identity.uid,
|
|
info: { email: @user.email, first_name: "Ben", last_name: "Jones" }
|
|
)
|
|
|
|
@oidc_identity.sync_user_attributes!(auth)
|
|
|
|
@user.reload
|
|
assert_equal "Adam", @user.first_name
|
|
assert_equal "Smith", @user.last_name
|
|
# Identity record itself still mirrors the IdP for audit / debugging.
|
|
assert_equal "Ben", @oidc_identity.info["first_name"]
|
|
assert_equal "Jones", @oidc_identity.info["last_name"]
|
|
end
|
|
|
|
test "sync_user_attributes! fills blank user names from the IdP" do
|
|
@user.update!(first_name: nil, last_name: nil)
|
|
auth = OmniAuth::AuthHash.new(
|
|
provider: @oidc_identity.provider,
|
|
uid: @oidc_identity.uid,
|
|
info: { email: @user.email, first_name: "Ben", last_name: "Jones" }
|
|
)
|
|
|
|
@oidc_identity.sync_user_attributes!(auth)
|
|
|
|
@user.reload
|
|
assert_equal "Ben", @user.first_name
|
|
assert_equal "Jones", @user.last_name
|
|
end
|
|
|
|
test "creates from omniauth hash" do
|
|
auth = OmniAuth::AuthHash.new({
|
|
provider: "google_oauth2",
|
|
uid: "google-123456",
|
|
info: {
|
|
email: "test@example.com",
|
|
name: "Test User",
|
|
first_name: "Test",
|
|
last_name: "User"
|
|
}
|
|
})
|
|
|
|
identity = OidcIdentity.create_from_omniauth(auth, @user)
|
|
|
|
assert identity.persisted?
|
|
assert_equal "google_oauth2", identity.provider
|
|
assert_equal "google-123456", identity.uid
|
|
assert_equal "test@example.com", identity.info["email"]
|
|
assert_equal "Test User", identity.info["name"]
|
|
assert_equal @user, identity.user
|
|
assert_not_nil identity.last_authenticated_at
|
|
end
|
|
end
|