diff --git a/app/assets/javascripts/admin/controllers/admin-user-index.js b/app/assets/javascripts/admin/controllers/admin-user-index.js
index 92101bce2f2..8f58755ef06 100644
--- a/app/assets/javascripts/admin/controllers/admin-user-index.js
+++ b/app/assets/javascripts/admin/controllers/admin-user-index.js
@@ -132,6 +132,11 @@ export default Controller.extend(CanCheckEmails, {
.catch(() => bootbox.alert(I18n.t("generic_error")));
},
+ @discourseComputed("model.single_sign_on_record.last_payload")
+ ssoPayload(lastPayload) {
+ return lastPayload.split("&");
+ },
+
actions: {
impersonate() {
return this.model.impersonate();
@@ -321,5 +326,16 @@ export default Controller.extend(CanCheckEmails, {
resetPrimaryGroup() {
this.set("model.primary_group_id", this.originalPrimaryGroupId);
},
+
+ deleteSSORecord() {
+ return bootbox.confirm(
+ I18n.t("admin.user.sso.confirm_delete"),
+ I18n.t("no_value"),
+ I18n.t("yes_value"),
+ () => {
+ return this.model.deleteSSORecord();
+ }
+ );
+ },
},
});
diff --git a/app/assets/javascripts/admin/models/admin-user.js b/app/assets/javascripts/admin/models/admin-user.js
index 5882910093d..8d4b38baeaa 100644
--- a/app/assets/javascripts/admin/models/admin-user.js
+++ b/app/assets/javascripts/admin/models/admin-user.js
@@ -567,6 +567,16 @@ const AdminUser = User.extend({
_formatError(event) {
return `http: ${event.status} - ${event.body}`;
},
+
+ deleteSSORecord() {
+ return ajax(`/admin/users/${this.id}/sso_record.json`, {
+ type: "DELETE",
+ })
+ .then(() => {
+ this.set("single_sign_on_record", null);
+ })
+ .catch(popupAjaxError);
+ },
});
AdminUser.reopenClass({
diff --git a/app/assets/javascripts/admin/templates/user-index.hbs b/app/assets/javascripts/admin/templates/user-index.hbs
index 5cccf43e373..c043ce529f1 100644
--- a/app/assets/javascripts/admin/templates/user-index.hbs
+++ b/app/assets/javascripts/admin/templates/user-index.hbs
@@ -652,6 +652,16 @@
{{i18n "admin.user.sso.external_id"}}
{{sso.external_id}}
+ {{#if model.can_delete_sso_record}}
+
+ {{d-button
+ class="btn-danger"
+ action=(action "deleteSSORecord")
+ icon="far-trash-alt"
+ label="admin.user.sso.delete_sso_record"
+ }}
+
+ {{/if}}
{{i18n "admin.user.sso.external_username"}}
@@ -671,6 +681,16 @@
{{i18n "admin.user.sso.external_avatar_url"}}
{{sso.external_avatar_url}}
+ {{#if sso.last_payload}}
+
+
{{i18n "admin.user.sso.last_payload"}}
+
+ {{#each ssoPayload as |line|}}
+ {{line}}
+ {{/each}}
+
+
+ {{/if}}
{{/with}}
{{/if}}
diff --git a/app/assets/stylesheets/common/admin/users.scss b/app/assets/stylesheets/common/admin/users.scss
index dcc0b0e3d9e..28a8612c01c 100644
--- a/app/assets/stylesheets/common/admin/users.scss
+++ b/app/assets/stylesheets/common/admin/users.scss
@@ -49,6 +49,7 @@
max-width: 350px;
min-width: 50px;
margin-left: 12px;
+ word-break: break-word;
.select-kit {
min-width: 100px;
}
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 0deed95a8ab..48b292cc1c5 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -23,7 +23,8 @@ class Admin::UsersController < Admin::AdminController
:merge,
:reset_bounce_score,
:disable_second_factor,
- :delete_posts_batch]
+ :delete_posts_batch,
+ :sso_record]
def index
users = ::AdminUserIndexQuery.new(params).find_users
@@ -498,6 +499,12 @@ class Admin::UsersController < Admin::AdminController
render json: success_json
end
+ def sso_record
+ guardian.ensure_can_delete_sso_record!(@user)
+ @user.single_sign_on_record.destroy!
+ render json: success_json
+ end
+
private
def perform_post_action
diff --git a/app/serializers/admin_detailed_user_serializer.rb b/app/serializers/admin_detailed_user_serializer.rb
index 0f3840ed8ee..6dc9413ae41 100644
--- a/app/serializers/admin_detailed_user_serializer.rb
+++ b/app/serializers/admin_detailed_user_serializer.rb
@@ -31,6 +31,7 @@ class AdminDetailedUserSerializer < AdminUserSerializer
:can_view_action_logs,
:second_factor_enabled,
:can_disable_second_factor,
+ :can_delete_sso_record,
:api_key_count
has_one :approved_by, serializer: BasicUserSerializer, embed: :objects
@@ -126,4 +127,8 @@ class AdminDetailedUserSerializer < AdminUserSerializer
def api_key_count
object.api_keys.active.count
end
+
+ def can_delete_sso_record
+ scope.can_delete_sso_record?(object)
+ end
end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index e630d466b79..6e3878515fb 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -4626,6 +4626,9 @@ en:
external_name: "Name"
external_email: "Email"
external_avatar_url: "Profile Picture URL"
+ last_payload: "Last Payload"
+ delete_sso_record: "Delete SSO Record"
+ confirm_delete: "Are you sure you would like to delete this single sign on (SSO) record?"
user_fields:
title: "User Fields"
diff --git a/config/routes.rb b/config/routes.rb
index 47bc641eb5f..342ced7813f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -144,6 +144,7 @@ Discourse::Application.routes.draw do
post "merge"
post "reset_bounce_score"
put "disable_second_factor"
+ delete "sso_record"
end
get "users/:id.json" => 'users#show', defaults: { format: 'json' }
get 'users/:id/:username' => 'users#show', constraints: { username: RouteFormat.username }
diff --git a/lib/guardian/user_guardian.rb b/lib/guardian/user_guardian.rb
index aa917791849..6e2ccdb03cd 100644
--- a/lib/guardian/user_guardian.rb
+++ b/lib/guardian/user_guardian.rb
@@ -167,4 +167,7 @@ module UserGuardian
(is_me?(user) && user.has_trust_level?(SiteSetting.min_trust_level_to_allow_user_card_background.to_i)) || is_staff?
end
+ def can_delete_sso_record?(user)
+ SiteSetting.enable_sso && user && is_admin?
+ end
end
diff --git a/spec/requests/admin/users_controller_spec.rb b/spec/requests/admin/users_controller_spec.rb
index 14a6cb0196b..83bd456dfbe 100644
--- a/spec/requests/admin/users_controller_spec.rb
+++ b/spec/requests/admin/users_controller_spec.rb
@@ -1049,4 +1049,17 @@ RSpec.describe Admin::UsersController do
end
end
+ describe '#sso_record' do
+ fab!(:sso_record) { SingleSignOnRecord.create!(user_id: user.id, external_id: '12345', external_email: user.email, last_payload: '') }
+
+ it "deletes the record" do
+ SiteSetting.sso_url = "https://www.example.com/sso"
+ SiteSetting.enable_sso = true
+
+ delete "/admin/users/#{user.id}/sso_record.json"
+ expect(response.status).to eq(200)
+ expect(user.single_sign_on_record).to eq(nil)
+ end
+ end
+
end