允许使用 SSO 移除名称

使用 /admin/users/sync_sso 端点同步 SSO 数据时,即使不要求填写姓名,也无法从账户中移除某人的姓名。换句话说,无法将账户姓名从某个值更改为空。此问题出现在 full_name_required = false(且 sso_overrides_name = true)的情况下。

我认为问题出在这里:

但遗憾的是,我对 Ruby/Discourse 的了解还不够深入,无法提交 PR。

4 个赞

这对我来说感觉像是一个功能请求。目前,您可以使用管理 API 在这种情况下清除名称。参见:

1 个赞

抱歉,但我不同意。我不明白这为什么是一个功能请求而不是一个缺陷。

我理解有其他 API 端点可以使用。但 /admin/users/sync_sso 的主要目的正是为了让这类数据保持同步。它已经允许设置账户名称字段——这没问题。但它假设名称始终是必填字段,并且不允许将其设置为空。因此,它无法用于保持数据同步。

下面的代码在我的沙箱环境中似乎能按预期工作,但再次说明,我目前还不太有信心提交 PR。请随意使用或修改它等。

-    if SiteSetting.sso_overrides_name && user.name != name && name.present?
-      user.name = name || User.suggest_name(username.blank? ? email : username)
+    if SiteSetting.sso_overrides_name && user.name != name
+      if SiteSetting.full_name_required && name.present?
+        user.name = name || User.suggest_name(username.blank? ? email : username)
+      else
+        user.name = name
+      end

这是一个功能请求,语义存在歧义。缺少名称可能意味着:

  1. 清除名称
  2. 保留名称不变

你正在要求更改协议。我通常倾向于明确性,以避免 API 产生混淆。

2 个赞

我现在明白你的意思了。

再次说明,我对内部机制(或 Ruby)的了解还不够……但有没有办法判断请求中是否提供了 name 字段?如果该字段完全不存在,就不修改账户的 name 字段;如果提供了 name 字段,则进行设置(如果为空,则清空)。这样是否就能遵循“仅同步已提供的字段”这一协议或行为?

如果我说得没什么道理,请见谅——我只是想根据我的理解来弄明白这个问题。

问题在于,现在协议语义中,如果“name”参数存在且设置为空,其效果与不存在“name”参数相同,即不会对其进行任何修改。

此处的更改属于协议语义的变更。理论上,我们可以将其改为:name= 表示将 name 置空,而缺少 name 参数则表示“不修改 name

1 个赞

我们并不是要移除所有人的名字——用户在我们网站(SSO 提供商)更新账户时,会自行更新其数据。我们依赖 /admin/users/sync_sso 来保持 Discourse 账户中的数据(用户名、姓名、头像等)同步。姓名是一个可选字段,可以留空。

我刚刚意识到,问题不仅出现在姓名上,还出现在更新个人简介、头像等方面:如果这些 SSO 记录需要更新为空值,无论它们是必填字段还是可选字段,都无法通过 /admin/users/sync_sso 保持同步。

我理解有人可能依赖现有的行为(尽管此前无人报告过此问题?),但如果这是当前协议,那么它在实现同步 SSO 记录这一目标方面似乎存在显著局限性。

我也遇到了这个问题:普通用户无法自行删除自己的个人信息(如姓名、头像、个人简介、自定义字段等)从 Discourse 中移除,这带来的影响可想而知。

我同意不改变当前的运作语义,但能否允许我们在 SSO 载荷中将这些属性设置为 false,或采用类似方式,以明确指示删除它们?

1 个赞

以前,我们通过将对 /admin/users/sync_sso 的调用与对 /u/{username} 端点的另一个调用组合来绕过此 SSO 限制,只是为了清除名称(如果名称的新值为空)。

然而,这似乎在最近某个版本中也停止工作了,可能是因为它在更新名称之前会检查 sso_overrides_name = true

因此,目前在使用 SSO 和 sso_overrides_name = true 时,似乎无法通过 API 让 SSO 提供商清除 Discourse 上的名称字段。

@sam,您能看到任何绕过此的方法吗?

我猜我们的 sync_sso 路由需要一个额外的参数?比如 &clear_name 不确定。这感觉是个极端情况。空白名字的用例是什么?也许如果没有名字就设置为用户名,然后 UI 可以抑制重复。

对我来说,你认为这是一个极端情况(edge case)是很令人困惑的,所以我猜你一定习惯了名字是必填字段的情况。

我们的情况正好相反:用户名是每个人都必须有的,而名字是可选字段(我们使用 prioritize_username_in_ux = truefull name required = false)。想想 Twitter 账户,每个人都必须有一个用户名/句柄,并且可以选择性地添加一个名字。我不认为清除名字字段(或其他个人数据)是一种极端情况。

目前,一旦填写了名字,就无法将其删除。这是 sync_sso 的一个限制,我们通过额外的 API 调用来更新用户来解决,但现在这也不起作用了。

我们考虑过,但这会让一些人认为用户名也是他们的真实姓名:我们运营一个国际论坛,人们常常不清楚什么是姓名,什么是用户名(除了在界面上的位置)。

我应该提到,如果我没记错的话,通过 sync_sso 删除头像也会出现完全相同的问题,因为我认为那也不起作用——我们通过提供自己的默认头像 URL 来解决这个问题。

如果存在多个无法以某种方式清除的字段,也许可以提供一个数组(或 CSV 列表)来指定要清除/重置的字段?

要达成一致并找到完成此任务的方法需要什么?我很乐意在我的这一侧实现任何操作:一个新参数、一个特殊值、第二次 API 调用。但从我的角度来看,目前的情况并非边缘情况。就像上面 @mentalstring 所说,我正在与外部事实来源同步,其中设置个人资料图片和显示名称是可选的。用户可以不设置它们。Discourse 允许它们不被设置。如果您不使用 SSO,您可以自由地设置和删除它们。DiscourseConnect 会破坏这一点:一旦设置了它们,就永远无法删除它们,我认为这是一个(非常小的)错误。

我理解关于更改协议的担忧,在协议中空值目前意味着不更改。我个人不同意,我认为这是一种直接且合理的解释协议的方式,风险很小:系统发送名称和 avatar_url 值,但有时将其设置为空,并期望这表示保留旧值,这种情况会非常奇怪。而且,如果有任何系统这样做,后果只是名称和头像被取消设置,这应该是一个容易修复的问题。

但无论如何,我不想争论这一点,但我确实想说明这是一个必要的功能。我愿意提交 PR,我只是想知道什么解决方案会被接受。

提前表示感谢。

1 个赞

鉴于这种情况至少会影响 nameavatar_url,甚至可能影响其他字段(我认为也包括 website?),是否可以提供一个 reset_fields 参数,其中包含一个要清除的字段列表,而不是多个单独的 clear_x

对我们来说,如果能通过对 /u/{username} 端点的附加调用来修复它就已经很有用了,但该端点在某个时候也停止工作了。

1 个赞