Browse Source

Fixes #4225 - Possibility to disable the classic password login.

Tobias Schäfer 2 years ago
parent
commit
aff68411b5

+ 10 - 1
app/assets/javascripts/app/controllers/_profile/password.coffee

@@ -84,4 +84,13 @@ class ProfilePassword extends App.ControllerSubContent
 
     @formEnable( @$('form') )
 
-App.Config.set('Password', { prio: 2000, name: __('Password'), parent: '#profile', target: '#profile/password', controller: ProfilePassword, permission: ['user_preferences.password'] }, 'NavBarProfile')
+App.Config.set('Password', {
+  prio: 2000,
+  name: __('Password'),
+  parent: '#profile',
+  target: '#profile/password',
+  controller: ProfilePassword,
+  permission: (controller) ->
+    return false if !App.Config.get('user_show_password_login') && !controller.permissionCheck('admin.*')
+    return controller.permissionCheck('user_preferences.password')
+}, 'NavBarProfile')

+ 63 - 0
app/assets/javascripts/app/controllers/admin_password_auth.coffee

@@ -0,0 +1,63 @@
+class AdminPasswordAuth extends App.ControllerFullPage
+  events:
+    'submit form':   'submit'
+    'click .submit': 'submit'
+    'click .retry':  'retry'
+  forceRender: true
+  className: 'admin_password_auth'
+
+  constructor: ->
+    super
+
+    # go back if password login is enabled
+    if @Config.get('user_show_password_login')
+      @navigate '#'
+      return
+
+    # if we are logged in, no admin password auth is wanted, redirect to app
+    if @authenticateCheck()
+      @navigate '#'
+      return
+
+    # set title
+    @title __('Admin Password Login')
+    @navupdate '#admin_password_auth'
+
+    @render()
+
+  render: (params) ->
+    configure_attributes = [
+      { name: 'username', display: __('Enter your username or email address'), tag: 'input', type: 'text', limit: 100, null: false, class: 'input span4' }
+    ]
+
+    @replaceWith(App.view('admin_password_auth/request')(params))
+
+    @form = new App.ControllerForm(
+      el:        @el.find('.js-adminPassword')
+      model:     { configure_attributes: configure_attributes }
+      autofocus: true
+    )
+
+  retry: (e) ->
+    e.preventDefault()
+    @render()
+
+  submit: (e) ->
+    e.preventDefault()
+    params = @formParam(e.target)
+    @formDisable(e)
+
+    # get data
+    @ajax(
+      id:          'admin_password_auth'
+      type:        'POST'
+      url:         "#{@apiPath}/users/admin_password_auth"
+      data:        JSON.stringify(params)
+      processData: true
+      success:     @success
+    )
+
+  success: (data) =>
+    @html(App.view('admin_password_auth/request_sent')())
+
+App.Config.set('admin_password_auth', AdminPasswordAuth, 'Routes')

+ 27 - 3
app/assets/javascripts/app/controllers/login.coffee

@@ -24,8 +24,29 @@ class Login extends App.ControllerFullPage
       }
 
     @title __('Sign in')
-    @render(data)
-    @navupdate '#login'
+
+    if !App.Config.get('user_show_password_login') && @password_auth_token
+      params =
+        token: @password_auth_token
+      @ajax(
+        id:          'admin_password_auth_verify'
+        type:        'POST'
+        url:         "#{@apiPath}/users/admin_password_auth_verify"
+        data:        JSON.stringify(params)
+        processData: true
+        success:     (verify_data, status, xhr) =>
+          if verify_data.message is 'ok'
+            data.showAdminPasswordLogin = true
+            data.username = verify_data.user_login
+          else
+            data.showAdminPasswordLoginFailed = true
+
+          @render(data)
+          @navupdate '#login'
+      )
+    else
+      @render(data)
+      @navupdate '#login'
 
     # observe config changes related to login page
     @controllerBind('config_update_local', (data) =>
@@ -35,10 +56,12 @@ class Login extends App.ControllerFullPage
         data.name != 'user_create_account' &&
         data.name != 'product_name' &&
         data.name != 'product_logo' &&
-        data.name != 'fqdn'
+        data.name != 'fqdn' &&
+        data.name != 'user_show_password_login'
       @render()
       'rerender'
     )
+
     @controllerBind('ui:rerender', =>
       @render()
     )
@@ -123,4 +146,5 @@ class Login extends App.ControllerFullPage
     )
 
 App.Config.set('login', Login, 'Routes')
+App.Config.set('login/admin/:password_auth_token', Login, 'Routes')
 App.Config.set('session_timeout', Login, 'Routes')

+ 19 - 0
app/assets/javascripts/app/views/admin_password_auth/request.jst.eco

@@ -0,0 +1,19 @@
+<div class="request_admin_password_auth fullscreen">
+  <div class="fullscreen-center">
+    <div class="hero-unit fullscreen-body">
+      <h2><%- @T('Request password login for admin?') %><small></small></h2>
+      <form class="js-adminPasswordAuthForm">
+        <div class="js-adminPassword"></div>
+        <div class="form-controls">
+          <a class="btn btn--text btn--subtle js-cancel" href="#login"><%- @T('Cancel & Go Back') %></a>
+          <button class="btn btn--primary js-submit align-right"><%- @T('Submit') %></button>
+        </div>
+      </form>
+    </div>
+  </div>
+  <div class="poweredBy">
+    <a href="https://zammad.org" target="_blank"><%- @Icon('logo') %></a>
+    <%- @T('Powered by') %>
+    <a href="https://zammad.org" target="_blank"><%- @Icon('logotype', 'logotype') %></a>
+  </div>
+</div>

+ 17 - 0
app/assets/javascripts/app/views/admin_password_auth/request_sent.jst.eco

@@ -0,0 +1,17 @@
+<div class="request_admin_password_auth fullscreen">
+  <div class="fullscreen-center">
+    <div class="hero-unit fullscreen-body">
+      <h2><%- @T('We\'ve sent admin password login instructions to your email address.') %><small></small></h2>
+      <p><%- @T('If you don\'t receive instructions within a minute or two, check your email\'s spam and junk filters, or try resending your request.') %></p>
+      <div class="form-controls">
+        <a class="btn btn--text btn--subtle js-cancel" href="#login"><%- @T('Cancel & Go Back') %></a>
+        <button class="btn btn--primary retry align-right"><%- @T('again') %></button>
+      </div>
+    </div>
+  </div>
+  <div class="poweredBy">
+    <a href="https://zammad.org" target="_blank"><%- @Icon('logo') %></a>
+    <%- @T('Powered by') %>
+    <a href="https://zammad.org" target="_blank"><%- @Icon('logotype', 'logotype') %></a>
+  </div>
+</div>

+ 65 - 36
app/assets/javascripts/app/views/login.jst.eco

@@ -10,50 +10,66 @@
         <div class="hero-unit alert alert--success js-maintenanceLogin"><%- @C('maintenance_login_message') %></div>
       <% end %>
 
+      <% user_show_password_login = @C('user_show_password_login') || _.isEmpty(@auth_providers) %>
+
       <div class="hero-unit">
         <img class="company-logo" src="<%= @logoUrl %>" alt="<%= @C('product_name') %>">
-        <form id="login">
-          <% if @item.errorMessage: %>
-            <div class="alert alert--danger" role="alert">
-              <%= @item.errorMessage %>
-            </div>
-          <% end %>
+        <% if @item.showAdminPasswordLogin || user_show_password_login: %>
+          <form id="login">
+            <% if @item.errorMessage: %>
+              <div class="alert alert--danger" role="alert">
+                <%= @item.errorMessage %>
+              </div>
+            <% end %>
 
-          <div class="form-group">
-            <div class="formGroup-label">
-              <label for="username"><%- @Ti('Username / email') %></label>
+            <div class="form-group">
+              <div class="formGroup-label">
+                <label for="username"><%- @Ti('Username / email') %></label>
+              </div>
+              <input id="username" name="username" type="text" class="form-control" value="<%= @item.username %>" autocapitalize="off" />
             </div>
-            <input id="username" name="username" type="text" class="form-control" value="<%= @item.username %>" autocapitalize="off" />
-          </div>
 
-          <div class="form-group">
-            <div class="formGroup-label">
-              <label for="password"><%- @Ti('Password') %></label>
+            <div class="form-group">
+              <div class="formGroup-label">
+                <label for="password"><%- @Ti('Password') %></label>
+              </div>
+              <input id="password" name="password" type="password" class="form-control" autocomplete="off"/>
             </div>
-            <input id="password" name="password" type="password" class="form-control" autocomplete="off"/>
-          </div>
 
-          <div class="form-group">
-            <label class="inline-label checkbox-replacement">
-              <input name="remember_me" value="1" type="checkbox">
-              <%- @Icon('checkbox', 'icon-unchecked') %>
-              <%- @Icon('checkbox-checked', 'icon-checked') %>
-              <span class="label-text"><%- @T('Remember me') %></span>
-            </label>
-          </div>
+            <div class="form-group">
+              <label class="inline-label checkbox-replacement">
+                <input name="remember_me" value="1" type="checkbox">
+                <%- @Icon('checkbox', 'icon-unchecked') %>
+                <%- @Icon('checkbox-checked', 'icon-checked') %>
+                <span class="label-text"><%- @T('Remember me') %></span>
+              </label>
+            </div>
 
-          <div class="form-controls">
-            <button class="btn btn--primary" type="submit"><%- @T('Sign in') %></button>
+            <div class="form-controls">
+              <button class="btn btn--primary" type="submit"><%- @T('Sign in') %></button>
 
-            <% if @C('user_lost_password'): %>
-              <a href="#password_reset" class="btn btn--text btn--secondary align-right"><%- @T('Forgot password?') %></a>
-            <% end %>
-          </div>
+              <% if @C('user_lost_password'): %>
+                <a href="#password_reset" class="btn btn--text btn--secondary align-right"><%- @T('Forgot password?') %></a>
+              <% end %>
+            </div>
 
-        </form>
+          </form>
+        <% else if @item.showAdminPasswordLoginFailed: %>
+          <form id="login">
+            <div class="alert alert--danger" role="alert">
+              <%- @T('The token for the admin password login is invalid.') %>
+            </div>
+          </form>
+        <% end %>
         <% if !_.isEmpty(@auth_providers): %>
           <div class="separator">
-            <span class="separator-text"><%- @T('or sign in using') %></span>
+            <span class="separator-text">
+              <% if @C('user_show_password_login'): %>
+                <%- @T('or sign in using') %>
+              <% else: %>
+                <%- @T('Sign in using') %>
+              <% end %>
+            </span>
           </div>
 
           <div class="auth-providers">
@@ -62,7 +78,9 @@
                 <input type="hidden" name="authenticity_token" value="<%= Spine.Ajax.defaults.headers['X-CSRF-Token'] %>">
                 <button type="submit" class="auth-provider auth-provider--<%= auth_provider.class %>">
                   <%- @Icon("#{auth_provider.class}-button", 'provider-icon') %>
-                  <span class="provider-name"><%- @T(auth_provider.name) %></span>
+                  <span class="provider-name">
+                    <%- @T(auth_provider.name) %>
+                  </span>
                 </button>
               </form>
             <% end %>
@@ -70,24 +88,35 @@
         <% end %>
       </div>
 
+    <% if user_show_password_login: %>
       <p>
         <%- @T("You're already registered with your email address if you've been in touch with our Support team.") %><br>
         <% if @C('user_lost_password'): %>
           <%- @T('You can request your password') %> <a href="#password_reset"><%- @T('here') %></a>.
         <% end %>
       </p>
+    <% end %>
+
+    <% if !user_show_password_login: %>
+      <p>
+        <%- @T('If you have problems with the third-party login you can request a one-time password login as an admin.') %>
+        <a href="#admin_password_auth"><%- @T('Request the password login here.') %></a>
+      </p>
+    <% end %>
 
-    <% if @C('user_create_account') || @public_links: %>
+    <% show_user_create_account = @C('user_create_account') && user_show_password_login %>
+    <% if show_user_create_account || !_.isEmpty(@public_links): %>
       <hr>
       <p>
-        <% if @C('user_create_account'): %>
+        <% if show_user_create_account: %>
           <a href="#signup"><%- @T('Register as a new customer') %></a>
         <% end %>
         <% for link, link_index in @public_links: %>
-          <% if link_index > 0 || @C('user_create_account'): %> | <% end %>
+          <% if link_index > 0 || show_user_create_account: %> | <% end %>
           <a href="<%= link.link %>" title="<% if link.description: %><%= link.description %><% else: %><%= link.title %><% end %>"<% if link.new_tab: %> target="_blank"<% end %>><%= link.title %></a>
         <% end %>
       </p>
+    <% end %>
     </div>
   </div>
   <div class="poweredBy">

+ 1 - 1
app/assets/javascripts/app/views/password/reset.jst.eco

@@ -10,7 +10,7 @@
         </div>
       </form>
     </div>
-  <% if @public_links: %>
+  <% if !_.isEmpty(@public_links): %>
     <p>
       <% for link, link_index in @public_links: %>
         <% if link_index > 0: %> | <% end %>

+ 1 - 1
app/assets/javascripts/app/views/password/reset_change.jst.eco

@@ -10,7 +10,7 @@
         </div>
       </form>
     </div>
-  <% if @public_links: %>
+  <% if !_.isEmpty(@public_links): %>
     <p>
       <% for link, link_index in @public_links: %>
         <% if link_index > 0: %> | <% end %>

+ 1 - 1
app/assets/javascripts/app/views/password/reset_failed.jst.eco

@@ -5,7 +5,7 @@
       <p><%- @message %></p>
       <a href="#password_reset" class="btn btn--text btn--secondary retry">&raquo; <%- @T('try again') %> &laquo;</a>
     </div>
-  <% if @public_links: %>
+  <% if !_.isEmpty(@public_links): %>
     <p>
       <% for link, link_index in @public_links: %>
         <% if link_index > 0: %> | <% end %>

+ 1 - 1
app/assets/javascripts/app/views/password/reset_sent.jst.eco

@@ -8,7 +8,7 @@
         <button class="btn btn--primary retry align-right"><%- @T('again') %></button>
       </div>
     </div>
-  <% if @public_links: %>
+  <% if !_.isEmpty(@public_links): %>
     <p>
       <% for link, link_index in @public_links: %>
         <% if link_index > 0: %> | <% end %>

Some files were not shown because too many files changed in this diff