mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 02:15:46 +08:00
f4f8a293e7
implemented review items. Blocking previous codes - valid 2-factor auth tokens can only be authenticated once/30 seconds. I played with updating the “last used” any time the token was attempted but that seemed to be overkill, and frustrating as to why a token would fail. Translatable texts. Move second factor logic to a helper class. Move second factor specific controller endpoints to its own controller. Move serialization logic for 2-factor details in admin user views. Add a login ember component for de-duplication Fix up code formatting Change verbiage of google authenticator add controller tests: second factor controller tests change email tests change password tests admin login tests add qunit tests - password reset, preferences fix: check for 2factor on change email controller fix: email controller - only show second factor errors on attempt fix: check against 'true' to enable second factor. Add modal for explaining what 2fa with links to Google Authenticator/FreeOTP add two factor to email signin link rate limit if second factor token present add rate limiter test for second factor attempts
571 lines
20 KiB
Handlebars
571 lines
20 KiB
Handlebars
<section class="details {{unless model.active 'not-activated'}}">
|
|
<div class='user-controls'>
|
|
{{#if model.canViewProfile}}
|
|
{{#link-to 'user' model class="btn"}}
|
|
{{d-icon "user"}}
|
|
{{i18n 'admin.user.show_public_profile'}}
|
|
{{/link-to}}
|
|
{{/if}}
|
|
|
|
{{#if model.can_view_action_logs}}
|
|
{{d-button action="viewActionLogs" actionParam=model.username icon="list-alt" label="admin.user.action_logs"}}
|
|
{{/if}}
|
|
{{#if model.active}}
|
|
{{#if model.can_impersonate}}
|
|
{{d-button class="btn-danger" action="impersonate" icon="crosshairs" label="admin.impersonate.title" title="admin.impersonate.help"}}
|
|
{{/if}}
|
|
{{#if currentUser.admin}}
|
|
{{d-button action="logOut" icon="power-off" label="admin.user.log_out"}}
|
|
{{/if}}
|
|
{{/if}}
|
|
{{plugin-outlet name="admin-user-controls-after" args=(hash model=model) tagName="" connectorTagName=""}}
|
|
</div>
|
|
|
|
<div class='display-row username'>
|
|
<div class='field'>{{i18n 'user.username.title'}}</div>
|
|
<div class='value'>
|
|
{{#if editingUsername}}
|
|
{{text-field value=userUsernameValue autofocus="autofocus"}}
|
|
{{else}}
|
|
<span {{action "toggleUsernameEdit"}}>{{model.username}}</span>
|
|
{{/if}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if editingUsername}}
|
|
{{d-button action="saveUsername" label="admin.user_fields.save"}}
|
|
<a href {{action "toggleUsernameEdit"}}>{{i18n 'cancel'}}</a>
|
|
{{else}}
|
|
{{d-button action="toggleUsernameEdit" icon="pencil"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'user.name.title'}}</div>
|
|
<div class='value'>
|
|
{{#if editingName}}
|
|
{{text-field value=userNameValue autofocus="autofocus"}}
|
|
{{else}}
|
|
<span {{action "toggleNameEdit"}}>{{model.name}}</span>
|
|
{{/if}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if editingName}}
|
|
{{d-button action="saveName" label="admin.user_fields.save"}}
|
|
<a href {{action "toggleNameEdit"}}>{{i18n 'cancel'}}</a>
|
|
{{else}}
|
|
{{d-button action="toggleNameEdit" icon="pencil"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
{{#if canCheckEmails}}
|
|
<div class='display-row email'>
|
|
<div class='field'>{{i18n 'user.email.title'}}</div>
|
|
<div class='value'>
|
|
{{#unless model.active}}
|
|
<div class='controls'>{{i18n 'admin.users.not_verified'}}</div>
|
|
{{/unless}}
|
|
{{#if model.email}}
|
|
<a href="mailto:{{unbound model.email}}">{{model.email}}</a>
|
|
{{else}}
|
|
{{d-button action="checkEmail" actionParam=model icon="envelope-o" label="admin.users.check_email.text" title="admin.users.check_email.title"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="display-row bounce-score">
|
|
<div class='field'><a href="{{model.bounceLink}}">{{i18n 'admin.user.bounce_score'}}</a></div>
|
|
<div class='value'>{{model.bounceScore}}</div>
|
|
<div class='controls'>
|
|
{{#if model.canResetBounceScore}}
|
|
{{d-button action="resetBounceScore" label="admin.user.reset_bounce_score.label" title="admin.user.reset_bounce_score.title"}}
|
|
{{/if}}
|
|
{{model.bounceScoreExplanation}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='display-row associations'>
|
|
<div class='field'>{{i18n 'user.associated_accounts'}}</div>
|
|
<div class='value'>
|
|
{{#if model.associated_accounts}}
|
|
{{model.associated_accounts}}
|
|
{{else}}
|
|
{{d-button action="checkEmail" actionParam=model icon="envelope-o" label="admin.users.check_email.text" title="admin.users.check_email.title"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'user.avatar.title'}}</div>
|
|
<div class='value'>{{avatar content imageSize="large"}}</div>
|
|
<div class="controls">
|
|
{{{i18n "admin.user.visit_profile" url=preferencesPath}}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'user.title.title'}}</div>
|
|
<div class='value'>
|
|
{{#if editingTitle}}
|
|
{{text-field value=userTitleValue autofocus="autofocus"}}
|
|
{{else}}
|
|
<span {{action "toggleTitleEdit"}}>{{model.title}} </span>
|
|
{{/if}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if editingTitle}}
|
|
{{d-button action="saveTitle" label="admin.user_fields.save"}}
|
|
<a href {{action "toggleTitleEdit"}}>{{i18n 'cancel'}}</a>
|
|
{{else}}
|
|
{{d-button action="toggleTitleEdit" icon="pencil"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='display-row last-ip'>
|
|
<div class='field'>{{i18n 'user.ip_address.title'}}</div>
|
|
<div class='value'>{{model.ip_address}}</div>
|
|
<div class='controls'>
|
|
{{#if currentUser.staff}}
|
|
{{d-button action="refreshBrowsers" label="admin.user.refresh_browsers"}}
|
|
{{ip-lookup ip=model.ip_address userId=model.id}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='display-row registration-ip'>
|
|
<div class='field'>{{i18n 'user.registration_ip_address.title'}}</div>
|
|
<div class='value'>{{model.registration_ip_address}}</div>
|
|
<div class='controls'>
|
|
{{#if currentUser.staff}}
|
|
{{ip-lookup ip=model.registration_ip_address userId=model.id}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
{{#if showBadges}}
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.badges.title'}}</div>
|
|
<div class='value'>
|
|
{{i18n 'badges.badge_count' count=model.badge_count}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#link-to 'adminUser.badges' model class="btn"}}{{d-icon "certificate"}}{{i18n 'admin.badges.edit_badges'}}{{/link-to}}
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'user.second_factor.title'}}</div>
|
|
<div class='value'>
|
|
{{#if model.second_factor_enabled}}
|
|
{{i18n "yes_value"}}
|
|
{{else}}
|
|
{{i18n "no_value"}}
|
|
{{/if}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if canDisableSecondFactor}}
|
|
{{d-button action="disableSecondFactor" icon="unlock-alt" label="user.second_factor.disable"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{{#if userFields}}
|
|
<section class='details'>
|
|
{{#each userFields as |uf|}}
|
|
<div class='display-row'>
|
|
<div class='field'>{{uf.name}}</div>
|
|
<div class='value'>
|
|
{{#if uf.value}}
|
|
{{uf.value}}
|
|
{{else}}
|
|
—
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
{{/each}}
|
|
</section>
|
|
{{/if}}
|
|
|
|
{{plugin-outlet name="admin-user-details" args=(hash model=model)}}
|
|
|
|
<section class='details'>
|
|
<h1>{{i18n 'admin.user.permissions'}}</h1>
|
|
|
|
{{#if showApproval}}
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.users.approved'}}</div>
|
|
<div class='value'>
|
|
{{#if model.approved}}
|
|
{{i18n 'admin.user.approved_by'}}
|
|
{{#link-to 'adminUser' approvedBy}}{{avatar model.approvedBy imageSize="small"}}{{/link-to}}
|
|
{{#link-to 'adminUser' approvedBy}}{{model.approvedBy.username}}{{/link-to}}
|
|
{{else}}
|
|
{{i18n 'no_value'}}
|
|
{{/if}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if model.approved}}
|
|
{{i18n 'admin.user.approve_success'}}
|
|
{{else}}
|
|
{{#if model.can_approve}}
|
|
{{d-button action="approve" icon="check" label="admin.user.approve"}}
|
|
{{/if}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.users.active'}}</div>
|
|
<div class='value'>{{i18n-yes-no model.active}}</div>
|
|
<div class='controls'>
|
|
{{#if model.active}}
|
|
{{#if model.can_deactivate}}
|
|
{{d-button action="deactivate" label="admin.user.deactivate_account"}}
|
|
{{i18n 'admin.user.deactivate_explanation'}}
|
|
{{/if}}
|
|
{{else}}
|
|
{{#if model.can_send_activation_email}}
|
|
{{d-button action="sendActivationEmail" icon="envelope" label="admin.user.send_activation_email"}}
|
|
{{/if}}
|
|
{{#if model.can_activate}}
|
|
{{d-button action="activate" icon="check" label="admin.user.activate"}}
|
|
{{/if}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="display-row">
|
|
<div class='field'>{{i18n 'admin.user.staged'}}</div>
|
|
<div class='value'>{{i18n-yes-no model.staged}}</div>
|
|
<div class='controls'>{{i18n 'admin.user.staged_explanation'}}</div>
|
|
</div>
|
|
|
|
{{#if currentUser.admin}}
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.api.key'}}</div>
|
|
{{#if model.api_key}}
|
|
<div class='long-value'>
|
|
{{model.api_key.key}}
|
|
{{d-button action="regenerateApiKey" icon="undo" label="admin.api.regenerate"}}
|
|
{{d-button action="revokeApiKey" icon="times" label="admin.api.revoke"}}
|
|
</div>
|
|
{{else}}
|
|
<div class='value'>
|
|
—
|
|
</div>
|
|
<div class='controls'>
|
|
{{d-button action="generateApiKey" icon="key" label="admin.api.generate"}}
|
|
</div>
|
|
{{/if}}
|
|
</div>
|
|
{{/if}}
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.admin'}}</div>
|
|
<div class='value'>{{i18n-yes-no model.admin}}</div>
|
|
<div class='controls'>
|
|
{{#if model.can_revoke_admin}}
|
|
{{d-button action="revokeAdmin" icon="shield" label="admin.user.revoke_admin"}}
|
|
{{/if}}
|
|
{{#if model.can_grant_admin}}
|
|
{{d-button action="grantAdmin" icon="shield" label="admin.user.grant_admin"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.moderator'}}</div>
|
|
<div class='value'>{{i18n-yes-no model.moderator}}</div>
|
|
<div class='controls'>
|
|
{{#if model.can_revoke_moderation}}
|
|
{{d-button action="revokeModeration" icon="shield" label="admin.user.revoke_moderation"}}
|
|
{{/if}}
|
|
{{#if model.can_grant_moderation}}
|
|
{{d-button action="grantModeration" icon="shield" label="admin.user.grant_moderation"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'trust_level'}}</div>
|
|
<div class="value">
|
|
{{combo-box content=site.trustLevels value=model.trust_level nameProperty="detailedName"}}
|
|
{{#if model.dirty}}
|
|
<div>
|
|
{{d-button class="ok no-text" action="saveTrustLevel" icon="check"}}
|
|
{{d-button class="cancel no-text" action="restoreTrustLevel" icon="times"}}
|
|
</div>
|
|
{{/if}}
|
|
</div>
|
|
<div class="controls">
|
|
{{#if model.canLockTrustLevel}}
|
|
{{#if model.manual_locked_trust_level}}
|
|
{{d-icon "lock" title="admin.user.trust_level_locked_tip"}}
|
|
{{d-button action="lockTrustLevel" actionParam=false label="admin.user.unlock_trust_level"}}
|
|
{{else}}
|
|
{{d-icon "unlock" title="admin.user.trust_level_unlocked_tip"}}
|
|
{{d-button action="lockTrustLevel" actionParam=true label="admin.user.lock_trust_level"}}
|
|
{{/if}}
|
|
{{/if}}
|
|
{{#if model.tl3Requirements}}
|
|
{{#link-to 'adminUser.tl3Requirements' model class="btn"}}{{i18n 'admin.user.trust_level_3_requirements'}}{{/link-to}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="user-suspended display-row {{if model.isSuspended 'highlight-danger'}}">
|
|
<div class='field'>{{i18n 'admin.user.suspended'}}</div>
|
|
<div class='value'>
|
|
{{i18n-yes-no model.isSuspended}}
|
|
{{#if model.isSuspended}}
|
|
{{#unless model.suspendedForever}}
|
|
{{i18n "admin.user.suspended_until" until=model.suspendedTillDate}}
|
|
{{/unless}}
|
|
{{/if}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if model.isSuspended}}
|
|
{{d-button
|
|
class="btn-danger unsuspend-user"
|
|
action=(action "unsuspend")
|
|
icon="ban"
|
|
label="admin.user.unsuspend"}}
|
|
{{i18n 'admin.user.suspended_explanation'}}
|
|
{{else}}
|
|
{{#if model.canSuspend}}
|
|
{{d-button
|
|
class="btn-danger suspend-user"
|
|
action=(action "showSuspendModal")
|
|
icon="ban"
|
|
label="admin.user.suspend"}}
|
|
{{i18n 'admin.user.suspended_explanation'}}
|
|
{{/if}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
|
|
{{#if model.isSuspended}}
|
|
<div class='display-row highlight-danger suspension-info'>
|
|
<div class='field'>{{i18n 'admin.user.suspended_by'}}</div>
|
|
<div class='value'>
|
|
{{#link-to 'adminUser' suspendedBy}}{{avatar model.suspendedBy imageSize="tiny"}}{{/link-to}}
|
|
{{#link-to 'adminUser' suspendedBy}}{{model.suspendedBy.username}}{{/link-to}}
|
|
</div>
|
|
<div class='controls'>
|
|
<b>{{i18n 'admin.user.suspend_reason'}}</b>:
|
|
<div class='full-reason'>{{model.full_suspend_reason}}</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
<div class="display-row {{if model.silenced 'highlight-danger'}}">
|
|
<div class='field'>{{i18n 'admin.user.silenced'}}</div>
|
|
<div class='value'>
|
|
{{i18n-yes-no model.silenced}}
|
|
{{#if model.isSilenced}}
|
|
{{#unless model.silencedForever}}
|
|
{{i18n "admin.user.suspended_until" until=model.silencedTillDate}}
|
|
{{/unless}}
|
|
{{/if}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#conditional-loading-spinner size="small" condition=model.silencingUser}}
|
|
{{#if model.silenced}}
|
|
{{d-button
|
|
class="btn-danger unsilence-user"
|
|
action="unsilence"
|
|
icon="microphone-slash"
|
|
label="admin.user.unsilence"}}
|
|
{{i18n 'admin.user.silence_explanation'}}
|
|
{{else}}
|
|
{{d-button
|
|
class="btn-danger silence-user"
|
|
action=(action "showSilenceModal")
|
|
icon="microphone-slash"
|
|
label="admin.user.silence"}}
|
|
{{i18n 'admin.user.silence_explanation'}}
|
|
{{/if}}
|
|
{{/conditional-loading-spinner}}
|
|
</div>
|
|
</div>
|
|
|
|
{{#if model.isSilenced}}
|
|
<div class='display-row highlight-danger silence-info'>
|
|
<div class='field'>{{i18n 'admin.user.silenced_by'}}</div>
|
|
<div class='value'>
|
|
{{#link-to 'adminUser' silencedBy}}{{avatar model.silencedBy imageSize="tiny"}}{{/link-to}}
|
|
{{#link-to 'adminUser' silencedBy}}{{model.silencedBy.username}}{{/link-to}}
|
|
</div>
|
|
<div class='controls'>
|
|
<b>{{i18n 'admin.user.silence_reason'}}</b>:
|
|
<div class='full-reason'>{{model.silence_reason}}</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
</section>
|
|
|
|
{{#if currentUser.admin}}
|
|
<section class='details'>
|
|
<h1>{{i18n 'admin.groups.title'}}</h1>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.groups.automatic'}}</div>
|
|
<div class='value'>{{automaticGroups}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.groups.custom'}}</div>
|
|
<div class='value'>
|
|
{{admin-group-selector selected=model.customGroups available=availableGroups}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if model.customGroups}}
|
|
{{i18n 'admin.groups.primary'}}
|
|
{{combo-box content=model.customGroups value=model.primary_group_id none="admin.groups.no_primary"}}
|
|
{{/if}}
|
|
{{#if primaryGroupDirty}}
|
|
{{d-button icon="check" class="ok" action="savePrimaryGroup"}}
|
|
{{d-button icon="times" class="cancel" action="resetPrimaryGroup"}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{{/if}}
|
|
|
|
<section class='details'>
|
|
<h1>{{i18n 'admin.user.activity'}}</h1>
|
|
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'created'}}</div>
|
|
<div class='value'>{{format-date model.created_at leaveAgo="true"}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.users.last_emailed'}}</div>
|
|
<div class='value'>{{format-date model.last_emailed_at}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'last_seen'}}</div>
|
|
<div class='value'>{{format-date model.last_seen_at leaveAgo="true"}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.like_count'}}</div>
|
|
<div class='value'>{{model.like_given_count}} / {{model.like_count}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.topics_entered'}}</div>
|
|
<div class='value'>{{model.topics_entered}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.post_count'}}</div>
|
|
<div class='value'>{{model.post_count}}</div>
|
|
<div class='controls'>
|
|
{{#if model.can_delete_all_posts}}
|
|
{{#if model.post_count}}
|
|
{{d-button class="btn-danger" action="deleteAllPosts" icon="trash-o" label="admin.user.delete_all_posts"}}
|
|
{{/if}}
|
|
{{else}}
|
|
{{model.deleteAllPostsExplanation}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.posts_read_count'}}</div>
|
|
<div class='value'>{{model.posts_read_count}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.warnings_received_count'}}</div>
|
|
<div class='value'>{{model.warnings_received_count}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.flags_given_received_count'}}</div>
|
|
<div class='value'>
|
|
{{model.flags_given_count}} / {{model.flags_received_count}}
|
|
</div>
|
|
<div class='controls'>
|
|
{{#if model.flags_received_count}}
|
|
{{d-button
|
|
action=(action "showFlagsReceived")
|
|
label="admin.user.show_flags_received"
|
|
icon="flag"
|
|
}}
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.private_topics_count'}}</div>
|
|
<div class='value'>{{model.private_topics_count}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.time_read'}}</div>
|
|
<div class='value'>{{{format-duration model.time_read}}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'user.invited.days_visited'}}</div>
|
|
<div class='value'>{{{model.days_visited}}}</div>
|
|
</div>
|
|
</section>
|
|
|
|
{{#if model.single_sign_on_record}}
|
|
<section class='details'>
|
|
<h1>{{i18n 'admin.user.sso.title'}}</h1>
|
|
|
|
{{#with model.single_sign_on_record as |sso|}}
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.sso.external_id'}}</div>
|
|
<div class='value'>{{sso.external_id}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.sso.external_username'}}</div>
|
|
<div class='value'>{{sso.external_username}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.sso.external_name'}}</div>
|
|
<div class='value'>{{sso.external_name}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.sso.external_email'}}</div>
|
|
<div class='value'>{{sso.external_email}}</div>
|
|
</div>
|
|
<div class='display-row'>
|
|
<div class='field'>{{i18n 'admin.user.sso.external_avatar_url'}}</div>
|
|
<div class='value'>{{sso.external_avatar_url}}</div>
|
|
</div>
|
|
{{/with}}
|
|
</section>
|
|
{{/if}}
|
|
|
|
<section>
|
|
<hr>
|
|
<div class="pull-right">
|
|
{{#unless model.anonymizeForbidden}}
|
|
{{d-button label="admin.user.anonymize"
|
|
icon="exclamation-triangle"
|
|
class="btn-danger"
|
|
disabled=model.anonymizeForbidden
|
|
action="anonymize"}}
|
|
{{/unless}}
|
|
|
|
{{#unless model.deleteForbidden}}
|
|
{{d-button label="admin.user.delete"
|
|
icon="exclamation-triangle"
|
|
class="btn-danger"
|
|
disabled=model.deleteForbidden
|
|
action="destroy"}}
|
|
{{/unless}}
|
|
</div>
|
|
|
|
{{#if model.deleteExplanation}}
|
|
<div class="clearfix"></div>
|
|
<br>
|
|
<div class="pull-right">
|
|
{{d-icon "exclamation-triangle"}} {{model.deleteExplanation}}
|
|
</div>
|
|
{{/if}}
|
|
</section>
|
|
<div class="clearfix"></div>
|