Implement SSO overriding avatars.

Implemented by having Discourse download the image from the provided URL
and treating it as a custom upload.

Adds two more parameters to the SSO site’s response:

* `avatar_url` specifies the URL of the overriding avatar.
* `avatar_force_update` Discourse does not re-download avatars that
has already been download from the same URL. Setting this to true forces
Discourse to re-download the avatar in `avatar_url`

Note that both parameters are ignored if `sso_overrides_avatar` is set
to false.
This commit is contained in:
Wilhansen Li 2014-08-19 15:49:14 +08:00
parent 76e74f6a3b
commit e0f970326f
8 changed files with 46 additions and 12 deletions

View File

@ -12,6 +12,7 @@ export default ObjectController.extend({
allowAvatarUpload: Discourse.computed.setting('allow_uploaded_avatars'),
allowUserLocale: Discourse.computed.setting('allow_user_locale'),
ssoOverridesAvatar: Discourse.computed.setting('sso_overrides_avatar'),
selectedCategories: function(){
return [].concat(this.get("watchedCategories"), this.get("trackedCategories"), this.get("mutedCategories"));

View File

@ -82,9 +82,9 @@
{{bound-avatar model "large"}}
{{#if allowAvatarUpload}}
<button {{action showAvatarSelector}} class="btn pad-left no-text"><i class="fa fa-pencil"></i></button>
{{else}}
{{else}} {{#unless ssoOverridesAvatar}}
<a href="//gravatar.com/emails" target="_blank" title="{{i18n user.change_avatar.gravatar_title}}" class="btn no-text"><i class="fa fa-pencil"></i></a>
{{/if}}
{{/unless}} {{/if}}
</div>
</div>

View File

@ -121,9 +121,32 @@ class DiscourseSingleSignOn < SingleSignOn
user.name = User.suggest_name(name || username || email)
end
if SiteSetting.sso_overrides_avatar && (
avatar_force_update == "true" ||
avatar_force_update.to_i != 0 ||
sso_record.external_avatar_url != avatar_url)
begin
tempfile = FileHelper.download(avatar_url, 1.megabyte, "sso-avatar")
upload = Upload.create_for(user.id, tempfile, "external-avatar", File.size(tempfile.path), { origin: avatar_url })
user.uploaded_avatar_id = upload.id
if !user.user_avatar.contains_upload?(upload.id)
user.user_avatar.custom_upload_id = upload.id
end
rescue SocketError
# skip saving, we are not connected to the net
Rails.logger.warn "Failed to download external avatar: #{avatar_url}, socket error - user id #{ user.id }"
ensure
tempfile.close! if tempfile && tempfile.respond_to?(:close!)
end
end
# change external attributes for sso record
sso_record.external_username = username
sso_record.external_email = email
sso_record.external_name = name
sso_record.external_avatar_url = avatar_url
end
end

View File

@ -6,15 +6,16 @@ end
#
# Table name: single_sign_on_records
#
# id :integer not null, primary key
# user_id :integer not null
# external_id :string(255) not null
# last_payload :text not null
# created_at :datetime
# updated_at :datetime
# external_username :string(255)
# external_email :string(255)
# external_name :string(255)
# id :integer not null, primary key
# user_id :integer not null
# external_id :string(255) not null
# last_payload :text not null
# created_at :datetime
# updated_at :datetime
# external_username :string(255)
# external_email :string(255)
# external_name :string(255)
# external_avatar_url :string(255)
#
# Indexes
#

View File

@ -769,6 +769,7 @@ en:
sso_overrides_email: "Overrides local email with external site email from SSO payload (WARNING: discrepancies can occur due to normalization of local emails)"
sso_overrides_username: "Overrides local username with external site username from SSO payload (WARNING: discrepancies can occur due to differences in username length/requirements)"
sso_overrides_name: "Overrides local name with external site name from SSO payload (WARNING: discrepancies can occur due to normalization of local names)"
sso_overrides_avatar: "Overrides user avatar with external site avatar from SSO payload. If enabled, disabling allow_uploaded_avatars is highly recommended"
enable_local_logins: "Enable local username and password login based accounts. (Note: this must be enabled for invites to work)"
allow_new_registrations: "Allow new user registrations. Uncheck this to prevent anyone from creating a new account."

View File

@ -229,6 +229,9 @@ login:
sso_overrides_email: false
sso_overrides_username: false
sso_overrides_name: false
sso_overrides_avatar:
default: false
client: true
users:

View File

@ -0,0 +1,5 @@
class AddExternalAvatarUrlToSingleSignOnRecord < ActiveRecord::Migration
def change
add_column :single_sign_on_records, :external_avatar_url, :string
end
end

View File

@ -1,5 +1,5 @@
class SingleSignOn
ACCESSORS = [:nonce, :name, :username, :email,
ACCESSORS = [:nonce, :name, :username, :email, :avatar_url, :avatar_force_update,
:about_me, :external_id]
FIXNUMS = []
NONCE_EXPIRY_TIME = 10.minutes