# Template updates

Note

The content of this page only applies to you if:

- You are using a custom LemonLDAP::NG theme

- AND you modified some of LemonLDAP::NG’s base templates (`login.tpl`, etc.).

Note that templates whose name start with `custom` (`customfooter.tpl`, etc.) do NOT count.

In other words, you can safely ignore this entire page if:

- You only changed the logo or background

- OR you created a custom theme and the only templates you modified are the ones that start with `custom` (`customfooter.tpl`, etc.)

## 2.23.0

### Fix auto-translation

Some web browsers might attempt to translate pages that are already in the correct language, to fix this, apply the following patch to `header.tpl`

    --- a/lemonldap-ng-portal/site/templates/bootstrap/header.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/header.tpl
    @@ -1,5 +1,5 @@
     <!DOCTYPE html>
    -<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
    +<html xmlns="http://www.w3.org/1999/xhtml"<TMPL_IF "LANGUAGE"> lang="<TMPL_VAR "LANGUAGE">"</TMPL_IF>>
     <head>
      <title trspan="authPortal">Authentication portal</title>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

### Rename 2FA

A new update button is added in 2FA manager to let users rename their 2FA.

    diff --git a/lemonldap-ng-portal/site/templates/bootstrap/2fregisters.tpl b/lemonldap-ng-portal/site/templates/bootstrap/2fregisters.tpl
    index dc3801b9d..fd5c84385 100644
    --- a/lemonldap-ng-portal/site/templates/bootstrap/2fregisters.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/2fregisters.tpl
    @@ -39,9 +39,21 @@
                     </TMPL_IF>
                 </TMPL_IF>
                 </td>
    -            <td class="align-middle"><TMPL_VAR NAME="name"></td>
    +            <td class="align-middle">
    +              <input id='input-<TMPL_VAR NAME="epoch">' type="text" class="form-control" value="<TMPL_VAR NAME="name">" />
    +            </td>
                 <td class="data-epoch"><TMPL_VAR NAME="epoch"></td>
                 <td>
    +               <span
    +                    device='<TMPL_VAR NAME="type">'
    +                    epoch='<TMPL_VAR NAME="epoch">'
    +                    prefix='<TMPL_VAR NAME="prefix">'
    +                    oldlabel='<TMPL_VAR NAME="name">'
    +                    class="btn btn-success update2f"
    +                    type="button">
    +                  <span class="fa fa-pencil"></span>
    +                  <span trspan="rename">Rename</span>
    +                </span>
                   <TMPL_IF NAME="delAllowed">
                     <span
                         device='<TMPL_VAR NAME="type">'

### Typo in oidcOfflineTokens.tpl

    diff --git a/lemonldap-ng-portal/site/templates/bootstrap/oidcOfflineTokens.tpl b/lemonldap-ng-portal/site/templates/bootstrap/oidcOfflineTokens.tpl
    index 2080d70f5ca15748e2c59908a3e753df1a06740e..cc7ad752c5e30eb27097345d7bcbf003d43a2794 100644
    --- a/lemonldap-ng-portal/site/templates/bootstrap/oidcOfflineTokens.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/oidcOfflineTokens.tpl
    @@ -1,4 +1,4 @@
    -<script type="text/javascript" src="<TMPL_VAR NAME="js">""></script>
    +<script type="text/javascript" src="<TMPL_VAR NAME="js">"></script>
     <script type="application/init">
     {"sessions":<TMPL_VAR NAME="sessions">}
     </script>

## 2.22.0

### Authentication choice

To prevent having a digit as first character of an identifier, the choice id value has been prefixed by `id_`. This could break the remember auth choice plugin if you have a customized `login.tpl`

    --- a/lemonldap-ng-portal/site/templates/bootstrap/login.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/login.tpl
    @@ -33,7 +33,7 @@
         <div class="collapse navbar-collapse" id="navbarSupportedContent">
           <ul class="navbar-nav mr-auto">
             <TMPL_LOOP NAME="AUTH_LOOP">
    -          <li class="nav-item" title="<TMPL_VAR NAME="key">"><a class="nav-link" href="#<TMPL_VAR NAME="key">"><TMPL_VAR NAME="name"></a></li>
    +          <li class="nav-item" title="<TMPL_VAR NAME="key">"><a class="nav-link" href="#id_<TMPL_VAR NAME="key">"><TMPL_VAR NAME="name"></a></li>
             </TMPL_LOOP>
           </ul>
         </div>
    @@ -44,7 +44,7 @@
           <!-- Forms -->
           <TMPL_LOOP NAME="AUTH_LOOP">

    -        <div id="<TMPL_VAR NAME="key">">
    +        <div id="id_<TMPL_VAR NAME="key">">

               <form id="lform<TMPL_VAR NAME="module">" action="<TMPL_VAR NAME="url">" method="post" class="login <TMPL_VAR NAME="module">">

### Prevent 2FA multiple submit

The way we prevent multiple submit of a form has changed.

We now catch the submit event of the form instead of the click event of the submit button.

This means the CSS class btn-single-submit must be removed from the submit button, and the data-property=”single-submit” must be added to the form.

We also add the required property to code input to avoid submitting an empty form.

    --- a/lemonldap-ng-portal/site/templates/bootstrap/ext2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/ext2fcheck.tpl
    @@ -10,7 +10,7 @@

     <div class="card">

    -<form action="<TMPL_IF "TARGET"><TMPL_VAR NAME="TARGET"><TMPL_ELSE>/ext2fcheck</TMPL_IF>" method="post" class="password" role="form">
    +<form action="<TMPL_IF "TARGET"><TMPL_VAR NAME="TARGET"><TMPL_ELSE>/ext2fcheck</TMPL_IF>" method="post" class="password" role="form" data-property="single-submit">
       <div class="form">
         <input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
         <input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" />
    @@ -20,7 +20,7 @@
           <div class="input-group-prepend">
             <span class="input-group-text"><label for="extcode" class="mb-0"><i class="fa fa-lock"></i></label></span>
           </div>
    -      <input name="code" value="" type="text" class="form-control" id="extcode" trplaceholder="code" autocomplete="one-time-code" />
    +      <input name="code" value="" type="text" class="form-control" id="extcode" trplaceholder="code" autocomplete="one-time-code"  required />
         </div>
       </div>
       <div class="buttons">

    --- a/lemonldap-ng-portal/site/templates/bootstrap/totp2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/totp2fcheck.tpl
    @@ -10,7 +10,7 @@

    <div class="card">

    -<form action="<TMPL_VAR NAME="TARGET">" method="post" class="password" role="form">
    +<form action="<TMPL_VAR NAME="TARGET">" method="post" class="password" role="form" data-property="single-submit">
       <div class="form">
         <input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
         <input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" />
    @@ -20,11 +20,11 @@
           <div class="input-group-prepend">
             <span class="input-group-text"><label for="extcode" class="mb-0"><i class="fa fa-lock"></i></label></span>
           </div>
    -      <input name="code" value="" type="text" class="form-control" id="extcode" trplaceholder="code" autocomplete="one-time-code" />
    +      <input name="code" value="" type="text" class="form-control" id="extcode" trplaceholder="code" autocomplete="one-time-code" required />
         </div>
       </div>
       <div class="buttons mb-3">
    -    <button type="submit" class="btn btn-success btn-single-submit">
    +    <button type="submit" class="btn btn-success">
           <span class="fa fa-sign-in"></span>
           <span trspan="connect">Connect</span>
         </button>

### Display if browser is already trusted

An information message is diplayed instead of the checkbox.

    --- a/lemonldap-ng-portal/site/templates/bootstrap/checklogins.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/checklogins.tpl
    @@ -12,6 +12,9 @@
         </div>
         </TMPL_IF>
         <TMPL_IF NAME="STAYCONNECTED">
    +      <TMPL_IF NAME="BROWSER_ALREADY_TRUSTED">
    +      <div class="message message-success alert alert-success"><span trspan="browserAlreadyTrusted">This browser is already trusted</span></div>
    +      <TMPL_ELSE>
         <div class="input-group mb-3">
           <div class="input-group-prepend">
             <div class="input-group-text">
    @@ -22,4 +25,5 @@
             <label id="stayConnectedLabel" for="stayconnected" trspan="stayConnected">Stay connected on this device</label>
           </p>
         </div>
    +      </TMPL_IF>
         </TMPL_IF>

## 2.21.0

### Floating category menu

You can now display an applications category as a floating menu by setting a category name in `General Parameters` > `Portal` > `Customization` > `Floating category name`. Apply the following patches to `menu.tpl`, `footer.tpl` and `script.tpl` to use this new feature:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/menu.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/menu.tpl
    @@ -129,7 +129,7 @@
                 <TMPL_IF NAME="category">
                 <!-- Category -->

    -              <div class="category cat-level-<TMPL_VAR NAME="catlevel"> <TMPL_VAR NAME="catid"> card border-secondary" id="sort_<TMPL_VAR NAME="__counter__">">
    +              <div class="category cat-level-<TMPL_VAR NAME="catlevel"> <TMPL_VAR NAME="catid"> card border-secondary" name="<TMPL_VAR NAME="catname">" id="sort_<TMPL_VAR NAME="__counter__">" >

                     <div class="card-header text-white bg-secondary">
                     <h4 class="catname card-title"><TMPL_VAR NAME="catname"><span><i class="fa fa-arrows-v float-right" ></i></span></h4>

    --- a/lemonldap-ng-portal/site/templates/bootstrap/footer.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/footer.tpl
    @@ -1,10 +1,12 @@
       </div>

    -<TMPL_IF NAME="SCROLL_TOP">
    -  <button type="button" class="btn btn-danger btn-floating btn-lg" id="btn-back-to-top">
    -    <i class="fa fa-arrow-circle-up"></i>
    -  </button>
    -</TMPL_IF>
    +  <TMPL_IF NAME="SCROLL_TOP">
    +    <button type="button" class="btn btn-danger btn-floating btn-lg" id="btn-back-to-top">
    +      <i class="fa fa-chevron-up"></i>
    +    </button>
    +  </TMPL_IF>
    +
    +  <div class="col-6" id="floating-menu"></div>

       <div id="footer">
         <div class="row">

    --- a/lemonldap-ng-portal/site/templates/common/script.tpl
    +++ b/lemonldap-ng-portal/site/templates/common/script.tpl
    @@ -49,7 +49,7 @@
      "enablePasswordDisplay":<TMPL_VAR NAME="ENABLE_PASSWORD_DISPLAY" DEFAULT="0">,
      "dontStorePassword":<TMPL_VAR NAME="DONT_STORE_PASSWORD" DEFAULT="0">,
      "scrollTop":<TMPL_VAR NAME="SCROLL_TOP" DEFAULT="0">,
    - "floatingId":<TMPL_VAR NAME="FLOATING_ID" DEFAULT="0">,
    + "floatingCategory":"<TMPL_VAR NAME="FLOATING_CAT">",
      "sameSite":"<TMPL_VAR NAME="SAMESITE">",
      "cookieSecure":<TMPL_VAR NAME="COOKIESECURE">,
      "csrf_token":"<TMPL_VAR NAME="CSRF_TOKEN">"

### Cache-busting tags

When upgrading to a new LemonLDAP::NG version, you may encounter bugs due to old, cached javascript and CSS files being still used by some web browsers. This version of LemonLDAP::NG introduces a `?v=` parameter in static resource URLs to avoid this. The version ID is incremented on every version change.

You can use the Cache-busting salt parameter in the manager to change the value, which will force a reload of static resources for all your users.

This change is not mandatory, but is recommended to avoid bugs. In order to implement it, add

`?v=<TMPL_VAR CACHE_TAG>` at the end of all static resource URLs in your custom templates.

### JWT headers restored

JSON-Web-Tokens didn’t have the “typ” header starting from version 2.17.0. This header is set to “JWT” except for access_token where value is “at+JWT”. If you encounter issues with this value, a parameter has been added in the manager to not insert the “typ” header into JWT: Don’t insert typ header.

## 2.20.0

### Password policy

The requirement for new password and new password confirmation to match is now displayed in the password policy, if you changed `passwordpolicy.tpl`, you need to update it:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl
    @@ -11,8 +11,9 @@
             </li>
             </TMPL_IF>
         </TMPL_LOOP>
    +    <li>
    +        <i id="samepassword-feedback" class="fa fa-li"> </i>
    +        <span trspan="passwordPolicySamePwd"></span>
    +    </li>
       </ul>
    -  <TMPL_IF NAME="PPOLICY_NOPOLICY">
    -    <span trspan="passwordPolicyNone">You are free to choose your password! ;-)</span>
    -  </TMPL_IF>
     </div>

### WebAuthn registration and authentication

If you modified the webauthn2fcheck.tpl or /webauthn2fregister.tpl, you will start noticing harmless but confusing error messages during WebAuthn checks or registration. In order to fix this, remove the javascript inclusions from both templates.

    --- a/lemonldap-ng-portal/site/templates/bootstrap/webauthn2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/webauthn2fcheck.tpl
    @@ -17,13 +17,6 @@
       <script type="application/init">
       <TMPL_VAR NAME="DATA">
       </script>
    -<!-- //if:jsminified
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthn-ui.min.js"></script>
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthncheck.min.js"></script>
    -//else -->
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthn-ui.js"></script>
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthncheck.js"></script>
    -<!-- //endif -->
     </TMPL_IF>

     </div>

    --- a/lemonldap-ng-portal/site/templates/bootstrap/webauthn2fregister.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/webauthn2fregister.tpl
    @@ -43,12 +43,4 @@
         <span trspan="goToPortal">Go to portal</span>
       </a>
     </div>
    -
    -<!-- //if:jsminified
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthn-ui.min.js"></script>
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthnregistration.min.js"></script>
    -//else -->
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthn-ui.js"></script>
    -  <script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/webauthnregistration.js"></script>
    -<!-- //endif -->
     <TMPL_INCLUDE NAME="footer.tpl">

Also update 2fregisters.tpl to that resident credentials are properly show to the user:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/2fregisters.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/2fregisters.tpl
    @@ -33,6 +33,11 @@
                 <TMPL_ELSE>
                     <TMPL_VAR NAME="type">
                 </TMPL_IF>
    +            <TMPL_IF name="type_WebAuthn">
    +                <TMPL_IF name="resident">
    +                <span trattribute="title:webauthnResident" class="fa fa-key"></span>
    +                </TMPL_IF>
    +            </TMPL_IF>
                 </td>
                 <td class="align-middle"><TMPL_VAR NAME="name"></td>
                 <td class="data-epoch"><TMPL_VAR NAME="epoch"></td>

### TOTP check

To avoid the TOTP code been submitted twice, add btn-single-submit class to TOTP check submit in totp2fcheck.tpl:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/totp2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/totp2fcheck.tpl
    @@ -24,7 +24,7 @@
         </div>
       </div>
       <div class="buttons mb-3">
    -    <button type="submit" class="btn btn-success">
    +    <button type="submit" class="btn btn-success btn-single-submit">
           <span class="fa fa-sign-in"></span>
           <span trspan="connect">Connect</span>
         </button>

### Vulnerability in templates

In order to fix a vulnerability in templates, apply the following patch:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/checkuser.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/checkuser.tpl
    @@ -11,7 +11,7 @@
             <div class="input-group-prepend">
               <span class="input-group-text"><label for="userfield" class="mb-0"><i class="fa fa-user"></i></label></span>
             </div>
    -        <input id="userfield" name="user" type="text" class="form-control" value="<TMPL_VAR NAME="LOGIN">" trplaceholder="user" aria-required="true"/>
    +        <input id="userfield" name="user" type="text" class="form-control" value="<TMPL_VAR NAME="LOGIN" ESCAPE=HTML>" trplaceholder="user" aria-required="true"/>
           </div>
           <div class="input-group mb-3">
             <div class="input-group-prepend">

    --- a/lemonldap-ng-portal/site/templates/bootstrap/globallogout.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/globallogout.tpl
    @@ -6,7 +6,7 @@
       <div class="row">
         <TMPL_IF NAME="SESSIONS">
         <div class="card col border-secondary">
    -      <div class="text-center bg-light text-dark"><b><span trspan="activeSessions">ACTIVE SSO SESSIONS</span>: <u><TMPL_VAR NAME="LOGIN"></u></b></div>
    +      <div class="text-center bg-light text-dark"><b><span trspan="activeSessions">ACTIVE SSO SESSIONS</span>: <u><TMPL_VAR NAME="LOGIN" ESCAPE=HTML></u></b></div>
           <table class="table table-sm table-hover text-center">
             <thead>
               <tr>

    --- a/lemonldap-ng-portal/site/templates/bootstrap/gpgform.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/gpgform.tpl
    @@ -5,7 +5,7 @@
         <div class="input-group-prepend">
           <span class="input-group-text"><label for="userfield" class="mb-0"><i class="fa fa-user"></i></label></span>
         </div>
    -    <input id="userfield" name="user" type="text" class="form-control" value="<TMPL_VAR NAME="LOGIN">" trplaceholder="mail" required aria-required="true" />
    +    <input id="userfield" name="user" type="text" class="form-control" value="<TMPL_VAR NAME="LOGIN" ESCAPE=HTML>" trplaceholder="mail" required aria-required="true" />
       </div>

       <div class="input-group mb-3">

    --- a/lemonldap-ng-portal/site/templates/bootstrap/password.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/password.tpl
    @@ -17,11 +17,11 @@

         <TMPL_IF NAME="LOGIN">
         <div class="input-group mb-3">
    -      <input name="user" type="hidden" value="<TMPL_VAR NAME=LOGIN>" />
    +      <input name="user" type="hidden" value="<TMPL_VAR NAME=LOGIN ESCAPE=HTML>" />
           <div class="input-group-prepend">
             <span class="input-group-text"><label for="staticUser" class="mb-0"><i class="fa fa-user"></i></label></span>
           </div>
    -      <input id="staticUser" type="text" readonly class="form-control" value="<TMPL_VAR NAME=LOGIN>" />
    +      <input id="staticUser" type="text" readonly class="form-control" value="<TMPL_VAR NAME=LOGIN ESCAPE=HTML>" />
         </div>
         </TMPL_IF>

### Multiple changes to login form

In order to implement WebAuthn changes, fix the template vulnerability, and improve focus management, update `standardform.tpl`:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/standardform.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/standardform.tpl
    @@ -10,21 +10,23 @@
         <div class="input-group-prepend">
           <span class="input-group-text"><label for="userfield" class="mb-0"><i class="fa fa-user"></i></label></span>
         </div>
    -    <input id="userfield" name="user" type="text" class="form-control" value="<TMPL_VAR NAME="LOGIN">" trplaceholder="login" required aria-required="true"/>
    +    <input id="userfield" name="user" type="text" class="form-control"
    +      value="<TMPL_IF NAME="ACTIVE_FORM"><TMPL_VAR NAME="LOGIN" ESCAPE=HTML></TMPL_IF>"
    +      trplaceholder="login" required aria-required="true" autocomplete="webauthn" <TMPL_UNLESS NAME="LOGIN">autofocus</TMPL_UNLESS> />
       </div>
       <div class="input-group mb-3">
         <div class="input-group-prepend">
           <span class="input-group-text"><label for="passwordfield" class="mb-0"><i class="fa fa-lock"></i></label></span>
         </div>
         <TMPL_IF NAME="DONT_STORE_PASSWORD">
    -      <input id="passwordfield" name="password" type="text" class="form-control" trplaceholder="password" autocomplete="off" required aria-required="true" aria-hidden="true"/>
    +      <input id="passwordfield" name="password" type="text" class="form-control" trplaceholder="password" autocomplete="off" required aria-required="true" aria-hidden="true" <TMPL_IF NAME="LOGIN">autofocus</TMPL_IF> />
           <TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
             <div class="input-group-append">
               <span class="input-group-text"><i id="toggle_password" class="fa fa-eye-slash toggle-password"></i></span>
             </div>
           </TMPL_IF>
         <TMPL_ELSE>
    -      <input id="passwordfield" name="password" type="password" class="form-control" trplaceholder="password" required aria-required="true"/>
    +      <input id="passwordfield" name="password" type="password" class="form-control" trplaceholder="password" required aria-required="true" <TMPL_IF NAME="LOGIN">autofocus</TMPL_IF> />
           <TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
             <div class="input-group-append">
               <span class="input-group-text"><i id="toggle_password" class="fa fa-eye-slash toggle-password"></i></span>

## 2.19.0

### TOTP registration

The TOTP registration now offers a `otpauth://` url that can automatically open your TOTP application when viewed on mobile. Apply the following patch to `totp2fregister.tpl` to use this new feature:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/totp2fregister.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/totp2fregister.tpl
    @@ -11,8 +11,8 @@
             <div class="col-md-6 text-center">
               <div >
                 <p>&#x2460; <span trspan="totpQrCode"></span></p>
    -            <canvas id="qr"></canvas>
    -
    +            <p><a class="otpauth-url" href=""><canvas id="qr"></canvas></a></p>
    +            <p><span trspan="totpOrTouch"></span></p>
                 <p><span trspan="totpSecretKey"></span></p>
                 <tt id="secret"></tt>
               </div>

### Second factor retry

It is recommended to apply the following patch to your custom templates so that users will have a more friendly error message when retrying their 2FA:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/ext2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/ext2fcheck.tpl
    @@ -2,7 +2,11 @@

     <main id="logincontent" class="container">

    +<TMPL_IF NAME="AUTH_ERROR">
    +  <div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert" role="<TMPL_VAR NAME="AUTH_ERROR_ROLE">"><span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span></div>
    +<TMPL_ELSE>
     <div class="message message-positive alert"><span trspan="<TMPL_IF "LEGEND"><TMPL_VAR "LEGEND"><TMPL_ELSE>enterExt2fCode</TMPL_IF>"></span></div>
    +</TMPL_IF>

     <div class="card">

    --- a/lemonldap-ng-portal/site/templates/bootstrap/password2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/password2fcheck.tpl
    @@ -2,7 +2,11 @@

     <main id="logincontent" class="container">

    +<TMPL_IF NAME="AUTH_ERROR">
    +  <div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert" role="<TMPL_VAR NAME="AUTH_ERROR_ROLE">"><span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span></div>
    +<TMPL_ELSE>
     <div class="message message-positive alert"><span trspan="enterPassword">Enter your password</span></div>
    +</TMPL_IF>

     <div class="card">

    --- a/lemonldap-ng-portal/site/templates/bootstrap/totp2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/totp2fcheck.tpl
    @@ -2,7 +2,11 @@

     <main id="logincontent" class="container">

    +<TMPL_IF NAME="AUTH_ERROR">
    +  <div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert" role="<TMPL_VAR NAME="AUTH_ERROR_ROLE">"><span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span></div>
    +<TMPL_ELSE>
     <div class="message message-positive alert"><span trspan="enterTotpCode"></span></div>
    +</TMPL_IF>

     <div class="card">

    --- a/lemonldap-ng-portal/site/templates/bootstrap/webauthn2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/webauthn2fcheck.tpl
    @@ -3,7 +3,7 @@
     <div class="container">

     <TMPL_IF NAME="AUTH_ERROR">
    -  <div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert"><span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span></div>
    +  <div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert" role="<TMPL_VAR NAME="AUTH_ERROR_ROLE">"><span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span></div>
     </TMPL_IF>
     <TMPL_IF NAME="DATA">
       <div id="color" class="message message-positive alert"><span id="msg" trspan="webAuthnRequired"></span></div>

## 2.18.0

### Password policy display

It is recommended to replace your custom theme’s `passwordpolicy.tpl` by the one that is provided in the `bootstrap` theme.

If you use the Have I Been Pwned plugin, this is a required change because the modifications in 2.18 will break this particular plugin.

If you are using the default templates from the `bootstrap` theme, you don’t need to change anything.

### Email templates

To avoid email sent by LL::NG being flagged as spam, we remove inline images in HTML content. You can add them back by customising the email templates and eithier use inline images (cid) or links to external resources.

Note that we now send a plain text version of the mail attached to the HTML email.

## 2.17.0

### Font Awesome application icons

It is now possible to use Font Awesome icons in the application menu.

If you modified the default `menu.tpl` template, you need to update it:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/menu.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/menu.tpl
    @@ -146,9 +146,13 @@
                             <!-- Logo (optional) -->
                             <TMPL_IF NAME="applogo">
                               <div class="col-3">
    +                          <TMPL_IF NAME="applogo_icon">
    +                          <span class="applogo fa-3x fa fa-<TMPL_VAR NAME="applogo"> <TMPL_VAR NAME="appid">"></span>
    +                          <TMPL_ELSE>
                               <img src="<TMPL_VAR NAME="STATIC_PREFIX">common/apps/<TMPL_VAR NAME="applogo">"
                                 class="applogo <TMPL_VAR NAME="appid"> img-fluid"
                                 alt="" />
    +                          </TMPL_IF>
                               </div>
                               <div class="col-9">
                             <TMPL_ELSE>

If you are using the default templates from the `bootstrap` theme, you don’t need to change anything.

### Password policy

It is recommended to update your theme’s `passwordpolicy.tpl` to correctly display special characters in password policies:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl
    @@ -34,7 +34,7 @@
         <TMPL_IF NAME="PPOLICY_ALLOWEDSPECHAR">
         <li>
             <i id="ppolicy-allowedspechar-feedback" class="fa fa-li"> </i>
    -        <span trspan="passwordPolicySpecialChar">Allowed special characters:</span> <TMPL_VAR NAME="PPOLICY_ALLOWEDSPECHAR">
    +        <span trspan="passwordPolicySpecialChar">Allowed special characters:</span> <TMPL_VAR NAME="PPOLICY_ALLOWEDSPECHAR" ESCAPE="html">
         </li>
         </TMPL_IF>
         <TMPL_IF NAME="ENABLE_CHECKHIBP">

If you are using the default templates from the `bootstrap` theme, you don’t need to change anything.

## 2.0.16

### Changes in templates

The default `skin.min.js` file has been updated in this release, be sure to copy `skin.min.js` from `bootstrap` into your custom theme.

Due to some internal changes in the way registrable second factors are handled, it is recommended to update your custom 2fregisters.tpl

    @@ -32,7 +32,14 @@
                 <td class="data-epoch"><TMPL_VAR NAME="epoch"></td>
                 <td>
                   <TMPL_IF NAME="delAllowed">
    -                <span device='<TMPL_VAR NAME="type">' epoch='<TMPL_VAR NAME="epoch">' class="btn btn-danger" role="button" data-toggle="modal" data-target="#remove2fModal">
    +                <span
    +                    device='<TMPL_VAR NAME="type">'
    +                    epoch='<TMPL_VAR NAME="epoch">'
    +                    prefix='<TMPL_VAR NAME="prefix">'
    +                    class="btn btn-danger"
    +                    role="button"
    +                    data-toggle="modal"
    +                    data-target="#remove2fModal">
                       <span class="fa fa-minus-circle"></span>
                       <span trspan="unregister">Unregister</span>
                        </span>

To fix behavior of checkbox “generate my password” in password reset screen, update your custom mail.tpl (see commit)

To have the new tooltip feature on IDP choice screen, update your custom idpchoice.tpl (see commit)

For the message box in menu when no applications are allowed, update your custom menu.tpl (see commit)

For the new password policy balcklist feature, update your custom passwordpolicy.tpl (see commit)

New template files that should be linked or copied in your custom theme:

- generic2fregister.tpl

- password2fcheck.tpl

- password2fregister.tpl

If you are using the default templates from the `bootstrap` theme, you don’t need to change anything.

## 2.0.15

### Re-send 2FA code

The mail, external and REST based 2FA types can now re-send the user code if delivery failed for some reason. If you use custom templates, you must update `ext2fcheck.tpl`

    --- a/lemonldap-ng-portal/site/templates/bootstrap/ext2fcheck.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/ext2fcheck.tpl
    @@ -26,6 +26,12 @@
         </button>
       </div>
       <div class="buttons">
    +    <TMPL_IF "RESENDTARGET">
    +    <button type="submit" class="btn btn-primary" formaction="<TMPL_VAR "RESENDTARGET">">
    +      <span class="fa fa-repeat"></span>
    +      <span trspan="resendCode">Re-send code</span>
    +    </button>
    +    </TMPL_IF>
         <a href="<TMPL_VAR NAME="PORTAL_URL">?cancel=1&skin=<TMPL_VAR NAME="SKIN">" class="btn btn-primary" role="button">
           <span class="fa fa-home"></span>
           <span trspan="cancel">Cancel</span>

If you are using the default templates from the `bootstrap` theme, you don’t need to change anything.

### Customizing the 2FA logo in the registration screen

The 2FA registration screen now displays the custom logo and label set in configuration. If you use custom templates, you should update `2fregisters.tpl`

    @@ -77,10 +77,16 @@
             <div class="card border-secondary">
               <div class="card-body py-3">
               <a href="<TMPL_VAR NAME="URL">" class="nodecor">
    -        <img src="<TMPL_VAR NAME="STATIC_PREFIX"><TMPL_VAR NAME="SKIN">/<TMPL_VAR NAME="LOGO">" alt="<TMPL_VAR NAME="CODE">2F" title="<TMPL_VAR NAME="CODE">2F" />
    +        <img src="<TMPL_VAR NAME="STATIC_PREFIX"><TMPL_VAR NAME="SKIN">/<TMPL_VAR NAME="LOGO">" alt="<TMPL_VAR NAME="CODE">2f" title="<TMPL_VAR NAME="LABEL">" />
               </a>
               </div>
    -      <div class="card-footer text-white text-uppercase bg-secondary"><TMPL_VAR NAME="CODE">2F</div>
    +      <div class="card-footer text-white text-uppercase bg-secondary">
    +      <TMPL_IF LABEL>
    +        <p><TMPL_VAR NAME="LABEL"></p>
    +      <TMPL_ELSE>
    +        <p trspan="<TMPL_VAR NAME="CODE">2f"></p>
    +      </TMPL_IF>
    +      </div>
             </div>
             </div>
             </TMPL_LOOP>

If you are using the default templates from the `bootstrap` theme, you don’t need to change anything.

### Remember authentication choice

A new plugin can be enabled to display a checkbox in authentication choice module to allow users remembering their choice, which will automatically redirect them to the selected choice the next time they connect to the portal.

If you use custom templates, you should update `login.tpl`

    --- a/lemonldap-ng-portal/site/templates/bootstrap/login.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/login.tpl
    @@ -66,6 +66,12 @@

                 <TMPL_IF NAME="sslform">
                   <TMPL_INCLUDE NAME="sslformChoice.tpl">
    +
    +              <!-- Remember my authentication choice for this module -->
    +              <TMPL_IF NAME="REMEMBERAUTHCHOICE">
    +                <input type="hidden" id="rememberauthchoice" name="rememberauthchoice" value="<TMPL_IF NAME="REMEMBERAUTHCHOICEDEFAULTCHECKED">true</TMPL_IF>" />
    +              </TMPL_IF>
    +
                 </TMPL_IF>

                 <TMPL_IF NAME="gpgform">
    @@ -92,6 +98,11 @@

                   </div>

    +              <!-- Remember my authentication choice for this module -->
    +              <TMPL_IF NAME="REMEMBERAUTHCHOICE">
    +                <input type="hidden" id="rememberauthchoice" name="rememberauthchoice" value="<TMPL_IF NAME="REMEMBERAUTHCHOICEDEFAULTCHECKED">true</TMPL_IF>" />
    +              </TMPL_IF>
    +
                 </TMPL_IF>

               </form>
    @@ -104,6 +115,34 @@

         </div> <!-- end authMenu -->

    +    <TMPL_IF NAME="REMEMBERAUTHCHOICE">
    +    <div class="input-group col-md-6 offset-md-3">
    +
    +      <!-- Global checkbox for remembering the authentication choice for all modules -->
    +      <div id="globalrememberauthchoicecontainer" class="input-group-prepend input-group">
    +        <div class="input-group-text">
    +          <input type="checkbox" id="globalrememberauthchoice" name="globalrememberauthchoice" aria-describedby="globalrememberauthchoiceLabel" <TMPL_IF NAME="REMEMBERAUTHCHOICEDEFAULTCHECKED">checked</TMPL_IF> />
    +          <input id="rememberCookieName" name="rememberCookieName" type="hidden" value="<TMPL_VAR NAME="REMEMBERAUTHCHOICECOOKIENAME">">
    +        </div>
    +          <p class="form-control">
    +            <label id="globalrememberauthchoiceLabel" for="globalrememberauthchoice" trspan="rememberChoice">Remember my choice</label>
    +          </p>
    +      </div>
    +
    +      <!-- Timer + stop button for triggering the remembered authentication choice -->
    +      <div id="remembertimercontainer" class="input-group">
    +        <p class="form-control">
    +          <span id="remembertimer"><TMPL_VAR NAME="REMEMBERAUTHCHOICETIMER"></span>
    +          <label id="rememberTimerLabel" trspan="rememberTimerLabel">s before automatic authentication</label>
    +        </p>
    +        <input id="rememberStopped" name="rememberStopped" type="hidden" value="">
    +        <div class="input-group-append inout-group">
    +          <button class="btn btn-danger" id="buttonRememberStopped"><i class="fa fa-stop-circle-o"></i> Stop</button>
    +        </div>
    +      </div>
    +    </div>
    +    </TMPL_IF>
    +
       </TMPL_IF>

       <TMPL_IF NAME="DISPLAY_FORM">

Copy also `styles.min.css` and `skin.min.js` from `bootstrap` into your custom theme.

If you are using the default templates from the `bootstrap` theme, you don’t need to change anything.

## 2.0.14

If you defined the “Register page URL” or the password “Reset page URL” to an external application, you need to fix the `standardform.tpl` template by applying the following patch:

    --- a/lemonldap-ng-portal/site/templates/bootstrap/standardform.tpl
    +++ b/lemonldap-ng-portal/site/templates/bootstrap/standardform.tpl
    @@ -48,14 +48,14 @@

     <div class="actions">
       <TMPL_IF NAME="DISPLAY_RESETPASSWORD">
    -  <a class="btn btn-secondary" href="<TMPL_VAR NAME="MAIL_URL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>">
    +  <a class="btn btn-secondary" href="<TMPL_VAR NAME="MAIL_URL"><TMPL_UNLESS NAME="MAIL_URL_EXTERNAL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF></TMPL_UNLESS>">
         <span class="fa fa-info-circle"></span>
         <span trspan="resetPwd">Reset my password</span>
       </a>
       </TMPL_IF>

       <TMPL_IF NAME="DISPLAY_UPDATECERTIF">
    -     <a class="btn btn-secondary" href="<TMPL_VAR NAME="MAILCERTIF_URL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>">
    +     <a class="btn btn-secondary" href="<TMPL_VAR NAME="MAILCERTIF_URL"><TMPL_UNLESS NAME="MAILCERTIF_URL_EXTERNAL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF></TMPL_UNLESS>">
             <span class="fa fa-refresh"></span>
             <span trspan="certificateReset">Reset my certificate</span>
          </a>
    @@ -69,7 +69,7 @@
       </TMPL_IF>

       <TMPL_IF NAME="DISPLAY_REGISTER">
    -    <a class="btn btn-secondary" href="<TMPL_VAR NAME="REGISTER_URL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>">
    +    <a class="btn btn-secondary" href="<TMPL_VAR NAME="REGISTER_URL"><TMPL_UNLESS NAME="REGISTER_URL_EXTERNAL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF></TMPL_UNLESS>">
           <span class="fa fa-plus-circle"></span>
           <span trspan="createAccount">Create an account</span>
         </a>

## 2.0.13

Some `autocomplete` attributes have been added to improve accessibility in the following files: `checkdevops.tpl`, `checkuser.tpl`, `register.tpl`, `ext2fcheck.tpl`, `totp2fcheck.tpl`.

## 2.0.12

### Email templates

If you customized the HTML email templates, you must update them to use HTML::Template variables (this was changed to fix XSS injections).

In the following files: `mail_2fcode.tpl` `mail_certificateReset.tpl` `mail_footer.tpl` `mail_password.tpl` `mail_register_done.tpl` `mail_certificateConfirm.tpl` `mail_confirm.tpl` `mail_header.tpl` `mail_register_confirm.tpl`

Replace the following variables:

Old syntax | New syntax
--- | ---
`$code` | `<TMPL_VAR NAME="code" ESCAPE=HTML>`
`$url` | `<TMPL_VAR NAME="url" ESCAPE=HTML>`
`$login` | `<TMPL_VAR NAME="login" ESCAPE=HTML>`
`$password` | `<TMPL_VAR NAME="password" ESCAPE=HTML>`
`$firstname` | `<TMPL_VAR NAME="firstname" ESCAPE=HTML>`
`$lastname` | `<TMPL_VAR NAME="lastname" ESCAPE=HTML>`

Replace all other variables such as `$cn` by `<TMPL_VAR NAME="session_cn" ESCAPE=HTML>`.

### Login form

To benefit from the new feature allowing to show password on login form, adapt `standardform.tpl` (see changes)

To disable password store in browser when changing password (this was already possible for login form), adapt `password.tpl` (see changes)

To fix placeholder display in password field when password store is disabled in browser, adapt `password.tpl` (see changes)

### Simplification of TOTP options

In `totp2fregister.tpl` template:

- Move `#divToHide` from the `.col-md-6` div to the `.card` div

- Change:

      <pre id="serialized"></pre>

- to:

      <br/><tt id="secret"></tt>

- Remove the `#changekey` button

### FindUser, CheckDevOps templates

Some changes have been made to include new plugins (FindUser and CheckDevOps), you need to report them only if you have a custom theme and you want to use these plugins

## 2.0.11

If you created your own skin and modified some template files, you may need to update them. No change is required if you are using the default `bootstrap` theme.

A new plugin has been introduced, in beta version: FindUser. It requires a modification of `login.tpl` to include `finduser.tpl`.

## 2.0.10

### 2FA manager

If you use a custom theme, even if you did not modify `2fregisters.tpl`, you need to copy `skin.min.js` from the `htdocs/static/bootstrap/js` folder to your custom theme’s `js` folder.

If you modified `2fregisters.tpl` you need to add the `remove2f` class to the button that triggers second factor removal:

    - <span device='<TMPL_VAR NAME="type">' epoch='<TMPL_VAR NAME="epoch">' class="btn btn-danger" role="button">
    + <span device='<TMPL_VAR NAME="type">' epoch='<TMPL_VAR NAME="epoch">' class="btn btn-danger remove2f" role="button">

Or, better yet, integrate the changes in `2fregisters.tpl` into your custom theme to benefit from the new 2F removal confirmation dialog

### Checkboxes

A CSS change has been done in `styles.css` to avoid checkbox labels overflow. See issue 2301.

The `form-check-input` class is missing in `register.tpl` and `notifinclude.tpl`. See issue 2374.

### Password checker

Input id values have been modified in `mail.tpl` to work with password checker. See issue 2355.

### Tables caption

Tables captions have been added in `sessionArray.tpl`. See issue 2356.

### Stay connected

A small change is required in `checklogins.tpl` for issue 2365.

Other changes needed in `2fchoice.tpl`, `ext2check.tpl` and `totp2fcheck.tpl` for issue 2366.

### Mails

The HTML `alt` attribute has been added on `img` in all `mail_*.tpl`. See issue 2422.