> ## Documentation Index
> Fetch the complete documentation index at: https://doc.lucidworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Appkit SDK 4.3.0 Release Notes

[localhost link]: http://localhost:3000/docs/4/app-studio/release-notes/appkit/4.3.0-release-notes

[mintlify link]: https://doc.lucidworks.com/docs/4/app-studio/release-notes/appkit/4.3.0-release-notes

[old doc.lw link]: https://doc.lucidworks.com/app-studio/4.2/982

**Release date:** 29 May 2019

## Upgrading to this version

In apps created with prior versions of Fusion App Studio, you can **Upgrade Appkit in Existing Apps**.

<Accordion title="Upgrade Appkit in Existing Apps">
  When you create an Appkit webapp, it uses a specific version of Appkit. Appkit releases occur independently of App Studio releases.

  You can upgrade web apps to use the latest version of Appkit.

  **How to upgrade**

  1. Stop the app.
  2. In the `package.json` file at the root of your project, update the `appkit-ui` dependency to the latest Appkit version, for example:

     ```json theme={"dark"}
     "appkit-ui": "http://appkit.lucidworks.com/repo/4.2.0/appkit-ui.tar.gz",
     ```
  3. In the `pom.xml` file at the root of your project, update the value of the `parent.version` property to the latest Appkit version, for example:

     ```xml theme={"dark"}
         <parent>
             <groupId>twigkit</groupId>
             <artifactId>twigkit.app.js</artifactId>
             <version>4.2.0</version>
         </parent>
     ```
  4. Upgrade the Appkit Social module, if required.
  5. Perform any additional upgrade steps that are required for a specific Appkit upgrade. See the [Appkit Release Notes](/docs/4/app-studio/release-notes/appkit/overview) for more information.
  6. Start the app.
</Accordion>

This section explains *additional steps* that are required or recommended (as indicated) for upgrading to this version of Appkit.

### Spring Security XML schema

**Update your apps that use Spring security to use version 4.2 of the Spring Security XML schema. In any application that has its own `spring-security.xml` file:**

1. Replace this Spring Security XML schema declaration:

   ```
   http://www.springframework.org/schema/security/spring-security-4.1.xsd

   ```

   With this one:

   ```
   http://www.springframework.org/schema/security/spring-security-4.2.xsd

   ```

### Using a Fusion service account for authentication and authorization

<Note>
  If you used a service account to authenticate against Fusion in a prior Appkit version, you must move the `userName` and `password` configuration values from your Fusion platform configuration to `services/api/fusion.conf` in this version.
</Note>

Service accounts no longer require the `impersonate` configuration option to be set to `true`. If the option is set to `true` in `services/api/fusion.conf`, it is ignored.

For more information, see [Fusion authorization](#fusion-authorization).

### Authorization and pre-authorization filters

For existing applications that implement custom `AuthorisationFilter` logic, you can and should re-implement those filters as instances of `PreAuthorisationFilter`, if the intention of those filters is not to authorize a request, but instead to augment the user object with pre-authorization information. However, this is not a necessary requirement for upgrading, because existing authorization filters work exactly as before. (They run after the pre-authorization filters.)

### Changing how to send signals to Fusion

<Note>
  This change was introduced in Appkit 4.0.0. If you have not already made this change, it is necessary now because the old approach to generating signals is [deprecated and has been removed](#deprecations).
</Note>

**How to change how signals are sent to Fusion**

1. Remove the following from your `pom.xml` file:

   ```
   <dependency>
       <groupId>twigkit</groupId>
       <artifactId>twigkit.activity.fusion-signals</artifactId>
       <version>${project.parent.version}</version>
   </dependency>

   ```

2. Add the following to your `pom.xml` file:

   ```
   <dependency>
       <groupId>twigkit</groupId>
       <artifactId>twigkit.activity.tracker</artifactId>
       <version>${project.parent.version}</version>
   </dependency>
   <dependency>
       <groupId>twigkit</groupId>
       <artifactId>twigkit.message.service.fusion.producer</artifactId>
       <version>${project.parent.version}</version>
   </dependency>

   ```

3. Add configuration parameters in `conf/message/service/fusion.conf`. You can send signal events to Fusion using either the Signals API or the Query API. This is an example in which the query-profile parameter is used to send events with the Fusion Query API:

   ```
   query-profile: my-profile
   commit: true
   async: false
   signals-index-pipeline: my-index-pipeline

   ```

   The parameter `signals-index-pipeline` is an optional parameter that defines a specific index pipeline to use when indexing signals. If no index pipeline is specified, the pre-configured `_signals_ingest` pipeline is used.

   <Note>
     The `signals-endpoint` configuration parameter is no longer supported.
   </Note>

4. By default, Appkit sends all events to the Signals endpoint. If you want to customize which events are sent, add a configuration file at `activity/tracking/tracker.conf` with the property `events`:

   ```
   events: click, request, response, login, annotation # or any subset thereof

   ```

<Note>
  A query pipeline automatically generates response signals when the signals feature is enabled for a collection. The search application should not send response signals to Fusion directly, because those would conflict with the automatically generated signals.
</Note>

## New features

* **JWT authorization against Fusion is supported.** Appkit now supports JSON Web Token (JWT) authorization against a Fusion JWT realm.\
  For information about options for authorization in Fusion, see [Fusion authorization](#fusion-authorization).

* **Discovery of Fusion proxy instances.** By default, Appkit now attempts to discover a Fusion Proxy service instance for querying. This removes the need to colocate a Fusion Proxy Service instance on every node running the Fusion Web Apps service.

  * If Appkit discovers a proxy, Appkit uses the discovered proxy instead of the configured `host` and `port` in `services/api/fusion.conf`.
  * If Appkit does not discover a proxy, Appkit uses the configured `host` and `port` in `services/api/fusion.conf`, or `localhost:8764` if the configuration values are not set.

  <Note>
    Proxy discovery uses the `fusion-proxy` Java system property, which is usually only available when an Appkit app runs on the Fusion Web Apps service.
  </Note>

  **Configuration:**

  To specify how Appkit finds a Fusion Proxy Service instance, define the property `fusion-discovery-enabled` in `services/api/fusion.conf`:

  * `fusion-discovery-enabled: true` (default if omitted). Appkit attempts to discover a Fusion proxy instance by reading the `fusion-proxy` Java system property. If it does not discover a proxy, Appkit uses the configured `host` and `port` in `services/api/fusion.conf`, or `localhost:8764` if the configuration values are not set.
  * `fusion-discovery-enabled: false`. Appkit does not attempt to discover a proxy, and uses the configured `host` and `port` in `services/api/fusion.conf`, or `localhost:8764` if the configuration values are not set.

    <Note>
      In an existing application that is deployed to Fusion, but that is not designed to query the Fusion server on which it is deployed for the location of the Fusion Proxy service, you must add the `fusion-discovery-enabled` parameter to `fusion.conf` with a value of `false` to retain the current behavior.
    </Note>

* **Role-based authorization.** Appkit adds an authorization filter that can authorize requests for protected resources based on the roles associated with the user who made the request. Security providers (such as SAML) or LDAP lookups can provide the roles.\
  For information, see [Role-based authorization](#role-based-authorization).

* **Solr JSON range facets.** Appkit now supports Solr JSON range facets as follows:

  * Appkit can now parse facets that were generated using JSON syntax and leverage them for display purposes in Appkit UI components.
  * Appkit cannot generate JSON facet query syntax (which needs to be manually input in the query pipeline or as query custom parameters).
  * Appkit cannot use the JSON facet’s filters to further refine query.

* **Localization.** Appkit replaces hard-coded labels (in English) with calls to an Appkit translation service. The service provides a label in the chosen language, with a fallback to English if no translation exists for the label in the chosen language. For more information, see [Localization service](#localization-service).

  <Note>
    This changes the [attributes for a number of tags](#tag-attribute-changes).
  </Note>

* **Stack traces in browser.** Appkit can send stack traces to the browser in responses (instead of HTML error pages) when run in development mode.\
  To enable full stack traces:

  1. Add a new filter, `twigkit.http.filter.DevelopmentErrorFilter`:

  ```xml theme={"dark"}
  <filter>
        <filter-name>ErrorFilter</filter-name>
        <filter-class>twigkit.http.filter.DevelopmentErrorFilter</filter-class>
  <!--        <init-param>-->
  <!--            <param-name>responseCode</param-name>-->
  <!--            <param-value>500</param-value>-->
  <!--        </init-param>-->
     </filter>
     <filter-mapping>
        <filter-name>ErrorFilter</filter-name>
        <url-pattern>*</url-pattern>
        <dispatcher>ERROR</dispatcher>
     </filter-mapping>

  ```

1. To only send stack traces for a subset of error response codes, e.g. 500 and 404,
   uncomment the `<init-param>` block and specify the response codes as a list of comma-separated values in `<param-value>`. For example:

   ```
   <init-param>
       <param-name>responseCode</param-name>
       <param-value>403,404,500</param-value>
   </init-param>

   ```

## Improvements

* **Retrieval of properties by workflow platforms.** If a platform is configured to be a workflow platform, platform property retrieval proceeds as follows:

  1. Appkit checks to see whether the workflow platform has a property.
  2. If the workflow platform does not have the property, Appkit checks to see whether the underlying platform has the property.
  3. If both the workflow platform and the underlying platform have the same property, the one defined for the workflow takes precedence.

* **Solr result clustering.** Appkit adds support for [Solr result clustering](https://lucene.apache.org/solr/guide/7_1/result-clustering.html).

* **No longer necessary to configure wt=xml in Fusion.** Appkit’s Solr Suggestions service that is used when backward compatibility is enabled (`SolrSuggestionsParserService`) now appends `wt=xml` to the Solr suggestions URL automatically. You no longer need to configure this query parameter in the Fusion query profile for suggestions.

* **Improved performance in Social module.** Performance of the Social module has been improved for annotation deletions.

* **Overwrite context path.** It is now possible to overwrite the context path. This is necessary when search app HTML files are hosted on one server and the Appkit APIs are on a different server.

* **No separate license restriction for Workflow module.** The separate license restriction for the Workflow module has been removed.

* **Lucene version.** The `twigkit.lucene` module now uses Lucene v7.2.1. You can use the `twigkit.lucene` module with other modules, for example, Elasticsearch 6, that use more recent versions of Lucene.

* **Default requestMethod for Solr search platform.** The default `requestMethod` for the Solr search platform has been changed from GET to POST.

## Role-based authorization

In many cases, you might want to restrict access to your application, or parts of your application, to specific groups of users. To enable this option, you must add the file `conf/security/access.conf` to your application’s configuration tree with these configuration parameters:

```yml wrap  theme={"dark"}
allow: role-with-access-1,role-with-access-2,...
deny: role-without-access-1,role-without-access-2,...
pattern: regex-of-uris-to-intercept
```

These configuration parameters are:

* `allow`: A comma-separated list of roles that should be granted access. When not specified or set to a wildcard ('\*'), Appkit defaults to allowing access to all roles.
* `deny`: A comma-separated list of roles that should be denied access.
* `pattern`: A regular expression that defines the pattern of URIs that should be intercepted for checking authorization. This defaults to .\* (all paths are checked).

### Example

Let us assume that you have a user directory containing two users, `user` and `admin`, where only the latter has an `ADMIN` role. For example, you can define this using a simple `spring-security.xml` configuration with a static list of users, like this:

```xml wrap  theme={"dark"}
<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user" password="user" authorities="USER"/>
            <user name="admin" password="admin" authorities="USER,ADMIN"/>
        </user-service>
    </authentication-provider>
</authentication-manager>
```

To configure role-based access, add `conf/security/access.conf` to the application with this configuration:

```yml wrap  theme={"dark"}
allow: ADMIN
pattern: (/)|(/twigkit/api/.*)
```

This says that, for all requests to `/` (the root page) and the API service, Appkit applies role-based authorization rules. Including the root page is not strictly necessary, but it leads to a better experience for users who are denied access.

To validate this setup, first log in as `user`. Appkit denies you access, as shown in the application logs:

```bash wrap  theme={"dark"}
TRACE t.s.SecurityFilterExecutionModule - Filtering with [twigkit.security.filter.RoleBasedAuthorizationFilter]
TRACE t.s.f.InterceptAuthorizationFilter - Filtering request to / - comparing against access pattern (/)|(/twigkit/api/.*)
TRACE t.s.f.RoleBasedAuthorizationFilter - User 'user' is DENIED access to protected resource
ERROR t.s.SecurityFilterExecutionModule - Authorization chain failed - returning 403
```

Next, log in as `admin`. Appkit allows you to access the app, as shown in the application logs:

```bash wrap  theme={"dark"}
TRACE t.s.SecurityFilterExecutionModule - Filtering with [twigkit.security.filter.RoleBasedAuthorisationFilter]
TRACE t.s.f.InterceptAuthorisationFilter - Filtering request to / - comparing against access pattern (/)|(/twigkit/api/.*)
TRACE t.s.f.RoleBasedAuthorisationFilter - User 'admin' is GRANTED access to protected resource
```

## Bug Fixes

* The default `requestMethod` for the Solr search platform has been changed to POST to avoid URL length limitations. Previously, the default was GET.

* An Apache Xerces dependency conflict between the SAML and Fusion security providers has been resolved.

* An error was corrected in the Spring security file `spring-security.xml` for Active Directory authentication. The `<security:loginForm>` tag lacked this line, which has been added:

```bash theme={"dark"}
 login-processing-url="/j_spring_security_check"
```

* When using the Social module with the Fusion platform, the index pipeline and query pipeline now default to `_system` if `social.conf` specifies the `collection`.\
  Instead of specifying the `collection` in `social.conf`, you can specify the `index-profile` and `query-profile`.

* The `slider` widget now submits the correct query.

* The bookmark icon on a result document now correctly indicates whether the document is bookmarked. Previously, deleting a bookmark from the bookmark list or search-box dropdown did not update the icon on the document.

* Click signals are now posted correctly to Fusion when Fusion is configured for single sign-on (SSO).

* The CSRF profile filter occasionally returns the wrong request tokens for a user.

* Previously, some query strings were incorrectly URL-encoded when being persisted in the Social module. The query strings are now persisted correctly.

* The `<search:facet>` tag now displays breadcrumb names such as `date` that were erroneously omitted.

* In the Social module, likes are now deleted when the user deselects the Like (thumb) icon.

* The task framework now allows completed tasks to be deleted.

* When using Appkit Guice security filters (not Spring security) failed authentication requests now return 401 rather than 200.

* When `label-field` is not set, Appkit no longer displays an empty tooltip when hovering over a marker on a map.

## New features

The following are new features in this release:

## Deprecations

The following are deprecations in this release:

* **Old method of sending signals to Fusion.** How to send signals to Fusion has changed in this release. The `twigkit.activity.fusion-signals` module is deprecated and has been removed.\
  Use the `twigkit.message.service.fusion.producer` module instead. For more information, see [Changing how to send signals to Fusion](#changing-how-to-send-signals-to-fusion).

* **Service account configuration option 'impersonate'.** Service accounts no longer require the `impersonate` configuration option to be set to `true`. If the option is set to `true` in `services/api/fusion.conf`, it is ignored.

An [alternative means of authorizing with a service account](#fusion-configuration) is provided.

<Note>
  If you used a service account to authenticate against Fusion in a prior Appkit version, you must move the `userName` and `password` configuration values from your Fusion platform configuration to `services/api/fusion.conf` in this version.
</Note>

## Improvements

The following are improvements in this release:

## Fusion authorization

Appkit now has three Fusion authorization modes:

| Mode                | Description                                                                                                                                                                                                                                                                                                                                 |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Fusion native realm | Authorization is against the [Fusion native security realm](/docs/4/fusion-server/concepts/security/access-control/security-realms) directly, using Fusion session passthrough. This is most useful for prototyping apps with Fusion’s Web Apps service.                                                                                    |
| Service account     | Authorization uses a service account in the Fusion native security realm. This is useful with external security providers, but entails having a username and password in the Appkit configuration.                                                                                                                                          |
| Fusion JWT realm    | Authorization is of individual users against the [Fusion JWT security realm](/docs/4/fusion-server/concepts/security/access-control/security-realms). This is also useful with external security providers, and there is no username and password in the Appkit configuration that might allow an attacker to gain access to the Fusion UI. |

Specify one of these modes or `auto` in the [Fusion authorization configuration](#fusion-authorization).

Service accounts no longer require the `impersonate` configuration option to be set to `true`. If the option is set to `true` in `services/api/fusion.conf`, it is ignored. An [alternative means of authorizing with a service account](#fusion-configuration) is provided.

<Note>
  If a configured authorization mode is not available (that is, configuration keys are missing), then Appkit uses the `native` mode as a fallback. An application is never left in a state in which it cannot at least try to authorize.
</Note>

### Configuration

By default, Appkit reads `services/api/fusion.conf` for configuration.

#### Fusion configuration

Provide the `auth` configuration parameter in `services/api/fusion.conf` to configure Fusion authorization. The `auth` parameter can have these values.

| Value            | Description                                                                                                                                                                                                                                                                                                                                 |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `native`         | Authorization is against the Fusion native realm directly, using Fusion session passthrough. This is most useful for prototyping apps with Fusion’s Web Apps service.                                                                                                                                                                       |
| `serviceaccount` | Authorization uses a service account in the [Fusion native security realm](/docs/4/fusion-server/concepts/security/access-control/security-realms). This is useful with external security providers, but entails having a username and password in the Appkit configuration.                                                                |
| `jwt`            | Authorization is of individual users against the [Fusion JWT security realm](/docs/4/fusion-server/concepts/security/access-control/security-realms). This is also useful with external security providers, and there is no username and password in the Appkit configuration that might allow an attacker to gain access to the Fusion UI. |
| `auto` (default) | Appkit searches for an available authentication provider in the order (1) `jwt`, (2) `serviceaccount`, and (3) `native`. Appkit uses the first authorization provider that confirms it has the necessary configuration to attempt authorization.                                                                                            |

#### Service account configuration

To configure Appkit for service account authorization against Fusion, include the following configuration options in `services/api/fusion.conf`:

| Option     | Description                                                   |
| ---------- | ------------------------------------------------------------- |
| `userName` | User name of the user for authorization (String, encryptable) |
| `password` | User’s password (String, encryptable)                         |

Service accounts no longer require the `impersonate` configuration option to be set to `true`. If the option is set to `true` in `services/api/fusion.conf`, it is ignored.

<Note>
  If you used a service account to authenticate against Fusion in a prior Appkit version, you must move the `userName` and `password` configuration values from your Fusion platform configuration to `services/api/fusion.conf` in this version.
</Note>

#### JWT configuration

To configure Appkit for JWT authorization against Fusion, include the following configuration options in `services/api/fusion.conf`:

| Option    | Description                                                                                                                                                                                       |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `issuer`  | Issuer that is configured in the Fusion JWT security realm  (String, encryptable)                                                                                                                 |
| `key`     | Key that is configured in the Fusion JWT security realm  (String, encryptable)                                                                                                                    |
| `groups`  | Group or list of groups. Groups must match those configured in the Fusion JWT security realm  (Comma-separated values, encryptable)                                                               |
| `subject` | Override the current user’s ID with this value. Use this when all JWT requests should be sent as a single user (for impersonation or service account emulation).  (String; optional, encryptable) |

#### Native configuration

No configuration is required for `native` authorization.

## App localization

You can localize the UI labels in an app in multiple languages of your choice.

## Localization service

Appkit obtains the correct labels for a language by making calls to an Appkit translation service. The service provides a label in the chosen language, with a fallback to English if no translation exists for the label in the chosen language.

### Loading translations

You can use the new `<translations:localize>` JSP tag to load a set of UI label translations into an app. The tag syntax is:

```xml wrap  theme={"dark"}
<translations:localize dictionary="*dictionary*" locale="*locale*" />
```

* **`dictionary`.** Name of the resource bundle from which to load translations. This is also the first part of the name of each property file that contains translations.\
  Default: `translations`
* **`locale`.** Locale\
  Default: `en` (English)

The `dictionary` and `locale` are used to find the file as follows:

1. In `src/main/resources`, the Appkit translation service looks for a resource bundle named `dictionary`, for example, `translations`.
2. Within the resource bundle, the translation service looks for property files named `dictionary_locale.properties`, for example, for the files `translations_en.properties` and `translations_fr.properties`.

### Enabling translations

1. Find label strings that need to be translated in the UI and identify the [key names for the labels](/docs/4/app-studio/concepts/configuration/localization-keys).

2. Create translation property files and add them to a resource bundle in `src/main/resources`. For example, add `translations_en.properties` and `translations_fr.properties` to the resource bundle `src/main/resources/translations`.

   Edit the property files and include the label keys and translations. For example:

   In `translations_en.properties`:

   ```
   # translations_en.properties
   ...
   components.pagination.next = Next
   components.pagination.previous = Previous
   ...

   ```

   In `translations_fr.properties`:

   ```
   # translations_fr.properties
   ...
   components.pagination.next = Suivant
   components.pagination.previous = Précédent
   ...

   ```

   <Note>
     Some translations include variables. For example, `components.response-statistics.showing` is `Showing {first} - {last} of {total}` in English. Translations should retain the variables, though their order might differ. Labels can use `<em>` tags for emphasis, for example, `More results like <em>{result}</em>`.
   </Note>

3. Add this `taglib` directive at the top of your app’s `index.jsp`:

   ```
   <%@ taglib prefix="translations" uri="/twigkit/translations" %>

   ```

4. Add the Appkit `<translations:localize>` JSP tag inside the `<head>` element of your app’s `index.jsp`:

   ```
   <translations:localize locale="${param.locale}" />

   ```

5. Add this rule to the `url-rules.xml` file:

   ```
   <!-- Language specific pages -->
   <rule>
       <from>^/lang/(.*)/</from>
       <to last="true">/index.jsp?locale=$1</to>
   </rule>

   ```

   <Note>
     You can modify other URL rules to suit your application logic. The \` JSP tag works the same.
   </Note>

6. Restart your app.

7. Verify that the translations are present by visiting pages in the app that should be in different languages.

### Tag attribute changes

There are localization-related attribute changes for these tags:

* `<collaborate:bookmark>`: Attributes `tooltip`, `active-tooltip`, `singular-tooltip`, and `plural-tooltip` have been removed.
* `<collaborate:bookmark-list>`: Attribute `empty-text` has been removed.
* `<collaborate:comment-list>`: Attributes `delete-label`, `show-more-label`, `show-less-label`, and `default-delete-message` have been removed.
* `<collaborate:like>`: Attributes `tooltip`, `active-tooltip`, `singular-tooltip`, and `plural-tooltip` have been removed.
* `<collaborate:topic-list>`: Attribute `empty-text` has been removed.
* `<search:breadcrumbs>`: Attribute `exclude-label` has been removed.
* `<search:facet>`: Attributes `show-more-label` and `show-less-label` have been removed.
* `<search:pagination>`: Attributes `next-label` and `previous-label` have been removed.
* `<search:response-statistics>`: Attributes `showing-all-label`, `showing-label`, `of-label`, and `to-label` have been removed.
* `<widget:spelling-suggestions>`: Attributes `label`, `original-label`, and `corrected-label` have been removed.
