# Jira & Confluence

* [jira](#jira)
  * [myself](#myself)
  * [check fields](#check-fields)
  * [check attachment](#check-attachment)
  * [list all projects](#list-all-projects)
  * [search issue by JQL](#search-issue-by-jql)
  * [\[get email address\](Get Email Addresses For Users)](#get-email-addressget-email-addresses-for-users)
  * [api token](#api-token)
  * [generate OAuth consumer](#generate-oauth-consumer)
  * [icons and priority](#icons-and-priority)
* [confluence](#confluence)
  * [myself](#myself-1)
  * [get info](#get-info)
  * [publish to confluence](#publish-to-confluence)
  * [plugins](#plugins)
  * [insert svg](#insert-svg)
* [CLI](#cli)
  * [running with docker images](#running-with-docker-images)
  * [create .acli.keystore](#create-aclikeystore)
  * [acli.properties](#acliproperties)

> \[!NOTE|label:reference:]
>
> * [\* Confluence REST API examples](https://developer.atlassian.com/server/confluence/confluence-rest-api-examples/)
> * [\* Jira REST API examples](https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/)
> * [Confluence Server REST API](https://developer.atlassian.com/server/confluence/confluence-server-rest-api/)
> * [./software/jira/docs/api/REST](https://docs.atlassian.com/software/jira/docs/api/REST/)
> * [JIRA Server platform REST API reference](https://docs.atlassian.com/software/jira/docs/api/REST/7.6.1/)
> * [Jenkins JIRA Pipeline Steps](https://jenkinsci.github.io/jira-steps-plugin/getting-started/)
>   * [Configuration](https://jenkinsci.github.io/jira-steps-plugin/getting-started/config/)
>     * [Authentication](https://jenkinsci.github.io/jira-steps-plugin/getting-started/config/authentication/)
>     * [Common Config](https://jenkinsci.github.io/jira-steps-plugin/getting-started/config/common/)
>     * [Jenkins Script](https://jenkinsci.github.io/jira-steps-plugin/getting-started/config/script/)
>     * [Configuration As Code Plugin](https://jenkinsci.github.io/jira-steps-plugin/getting-started/config/casc/)
>   * [Issue Steps](https://jenkinsci.github.io/jira-steps-plugin/steps/issue/)
>     * [jiraGetFields](https://jenkinsci.github.io/jira-steps-plugin/steps/issue/jira_get_fields/)
>     * [jiraGetIssue](https://jenkinsci.github.io/jira-steps-plugin/steps/issue/jira_get_issue/)
>     * [jiraEditIssue](https://jenkinsci.github.io/jira-steps-plugin/steps/issue/jira_edit_issue/)
>   * [Component Steps](https://jenkinsci.github.io/jira-steps-plugin/steps/component/)
>     * [jiraGetComponent](https://jenkinsci.github.io/jira-steps-plugin/steps/component/jira_get_component/)
>     * [jiraEditComponent](https://jenkinsci.github.io/jira-steps-plugin/steps/component/jira_edit_component/)
>     * [jiraGetComponentIssueCount](https://jenkinsci.github.io/jira-steps-plugin/steps/component/jira_get_component_issue_count/)
>   * [Comment Steps](https://jenkinsci.github.io/jira-steps-plugin/steps/comment/)
>     * [jiraGetComment](https://jenkinsci.github.io/jira-steps-plugin/steps/comment/jira_get_comment/)
>     * [jiraGetComments](https://jenkinsci.github.io/jira-steps-plugin/steps/comment/jira_get_comments/)
>     * [jiraAddComment](https://jenkinsci.github.io/jira-steps-plugin/steps/comment/jira_add_comment/)
>     * [jiraEditComment](https://jenkinsci.github.io/jira-steps-plugin/steps/comment/jira_edit_comment/)

### jira

{% hint style="info" %}

```bash
$ jiraName='jira.sample.com'
$ jiraID='STORY-1'
```

{% endhint %}

> \[!NOTE]
>
> * [Special headers](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#special-request-headers)
>   * `X-Atlassian-Token`
>   * `X-Force-Accept-Language`
>   * `X-AAccountId`

#### myself

> \[!NOTE|label:references:]
>
> * [Myself api v3](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-myself/#api-group-myself)
> * [Myself api v2](https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-myself/#api-group-myself)
> * [Zapier & API Tokens](https://wiki.resolution.de/doc/api-token-authentication/latest/user-guide/knowledge-base?)
> * [Add user preference keys to documentation for mypreferences endpoint in JIRA API](https://jira.atlassian.com/browse/JRASERVER-60067)

```bash
$ curl -s https://jira.sample.com/rest/api/2/myself
# or via `user?username=<id>`
$ curl -s https://jira.sample.com/rest/api/2/user?username=marslo
```

* get info

  ```bash
  # get timezone
  $ curl -s https://jira.sample.com/rest/api/2/mypreferences?key=jira.user.timezone
  Asia/Shanghai

  # get locale
  $ curl --request GET \
         --url 'https://jira.sample.com/rest/api/2/mypreferences/locale' \
         --header 'Accept: application/json'
  ```
* set info

  ```bash
  # set timezone
  $ curl --request PUT \
         --url 'https://jira.sample.com/rest/api/2/mypreferences?key={key}' \
         --header 'Accept: application/json' \
         --header 'Content-Type: application/json' \
         --data '"<string>"'

  # set local
  $ curl --request PUT \
         --url 'https://jira.sample.com/rest/api/2/mypreferences/locale' \
         --user 'email@example.com:<api_token>' \
         --header 'Accept: application/json' \
         --header 'Content-Type: application/json' \
         --data '{ "locale": "en_US" }'
  ```

#### check fields

```bash
$ curl -s \
       -k \
       -X GET https://${jiraName}/rest/api/2/issue/${jiraID} |
       jq --raw-output
```

#### check attachment

* check attachment ID

  ```bash
  $ curl -s \
         -k \
         -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
         jq --raw-output .fields.attachment[].id
  ```
* get attachments download url

  ```bash
  $ curl -s \
         -k \
         -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
         jq --raw-output .fields.attachment[].content
  ```

  * download all attachments in Jira

    > -I replace-str Replace occurrences of replace-str in the initial-arguments with names read from standard in- put. Also, unquoted blanks do not terminate input items; instead the separator is the new- line character. Implies -x and -L 1.

    ```bash
    $ curl -s \
           -k \
           -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
           jq --raw-output .fields.attachment[].content |
           xargs -I '{}' curl -sgOJL '{}'
    ```

#### list all projects

```bash
$ curl -fsSL -XGET https://jira.sample.com/rest/api/2/project |
  jq -r '.[] | [.key, .name] | join(" | ")' |
  column -s '|' -t
```

#### search issue by JQL

> \[!TIP]
>
> * [Search for issues using JQL (GET)](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-search/#api-rest-api-3-search-get)
> * [JQL: What is advanced search in Jira Cloud?](https://support.atlassian.com/jira-software-cloud/docs/what-is-advanced-search-in-jira-cloud/)
> * [How to get all issues by project key and issue type using REST api](https://community.developer.atlassian.com/t/how-to-get-all-issues-by-project-key-and-issue-type-using-rest-api/16074)
> * JQL pattern rule:
>   1. remove all space
>   2. `%3D` instead of `=`
>   3. `project=abc` -> `project%3Dabc`
>   4. `%20CONDITION%20` instead of `CONDITION`
>   5. `AND` -> `%20AND%20`
>   6. `OR` -> `%20OR%20`
> * [\* JQL operators](https://support.atlassian.com/jira-software-cloud/docs/jql-operators/)
> * [REST API - 'order by' param is ignored](https://community.atlassian.com/t5/Jira-Software-questions/REST-API-order-by-param-is-ignored/qaq-p/1696769#M483680)
> * [What is advanced search in Jira Cloud?](https://support.atlassian.com/jira-software-cloud/docs/what-is-advanced-search-in-jira-cloud/)

* format JQL

  > \[!TIP]
  >
  > * [\* iMarslo: using jql to get URLEncodign](https://github.com/marslo/ibook/blob/marslo/docs/cheatsheet/character/json.html#get-urlencode)

  ```bash
  $ jql='project = abc AND issuetype = release order by updated desc'
  $ jql=$(printf %s "${jql}" | jq -sRr @uri)
  ```

  ```bash
  $ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")"
  $ jql="$(printf %s "${jql}" | jq -sRr @uri)"

  # i.e.:
  $ jql='project = abc AND issuetype = release'

  $ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")"
  $ echo $jql
  project=abc AND issuetype=release

  $ jql="$(printf %s "${jql}" | jq -sRr @uri)"
  $ echo $jql
  project%3Dabc%20AND%20issuetype%3Drelease
  ```
* api

  > \[!NOTE]
  >
  > * [\* iMarslo : bin/jira](https://github.com/marslo/dotfiles/blob/main/.marslo/bin/jira)
  > * [query parameters](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-search/#api-rest-api-3-search-get):
  >   * `maxResults`: `integer`
  >   * `startAt`: `integer`
  >   * `validateQuery`: `string`
  >   * `fields`: `array<string>`
  >   * `expand`: `string`
  >   * `properties`: `array<string>`
  >   * `fieldsByKeys`: `boolean`
  >   * sample: `search?jql=${jql}&maxResults=100&startAt=0`

  ```bash
  $ curl --silent \
         --insecure \
         --globoff \
         --netrc-file ~/.netrc \
         -XGET \
         "https://jira.sample.com/rest/api/2/search?jql=${jql}" |
    jq -r ${jqOpt}

  # i.e.:
  $ curlOpt='--silent --insecure --globoff --netrc-file ~/.netrc'
  $ url='https://jira.sample.com/rest/api/2'
  $ queryParams="startAt=0&maxResults=10"

  $ jql='project = ABC AND issuetype = Release ORDER BY updated ASC'          # copy from Jira website
  $ jql="$(printf %s "${jql}" | jq -sRr @uri)"

  $ curl "${curlOpt}" "${url}/search?jql=${jql}&${queryParams}" |
         jq -r '.issues[]' |
         jq -r '. | [.key, .fields.summary, .fields.status.name, .fields.issuetype.name, .fields.updated, .fields.created] | join("|")' |
         while IFS='|' read -r _key _summary _status _issuetype _updated _created; do
           echo "- [${_key}] - ${_summary}"
           echo "  -  status    : ${_status}"
           echo "  -  issuetype : ${_issuetype}"
           echo "  -  created   : ${_created}"
           echo "  -  updated   : ${_updated}"
         done
  ```

  ```bash
  $ curl --silent \
         --insecure \
         --globoff \
         --netrc-file ~/.netrc \
         -XGET \
         "https://jira.sample.com/rest/api/2/search?jql=${jql}" |
    jq -r ${jqOpt}

  # i.e.:
  $ curlOpt='--silent --insecure --globoff --netrc-file ~/.netrc'
  $ url='https://jira.sample.com/rest/api/2'
  $ queryParams="startAt=0&maxResults=10"
  $ jql='project = abc AND issuetype = release'          # copy from Jira website

  $ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")"
  $ jql="$(printf %s "${jql}" | jq -sRr @uri)"

  $ curl "${curlOpt}" "${url}/search?jql=${jql}&${queryParams}" |
         jq -r '.issues[]' |
         jq -r '. | [.key, .fields.summary, .fields.status.name, .fields.issuetype.name, .fields.updated, .fields.created] | join("|")' |
         while IFS='|' read -r _key _summary _status _issuetype _updated _created; do
           echo "- [${_key}] - ${_summary}"
           echo "  -  status    : ${_status}"
           echo "  -  issuetype : ${_issuetype}"
           echo "  -  created   : ${_created}"
           echo "  -  updated   : ${_updated}"
         done
  ```

#### \[get email address]\(Get Email Addresses For Users)

```bash
$ curl GET https://jira.sample.com/rest/api/2/user?key=JIRAUSER10100 |
  jq -r
```

#### api token

> \[!NOTE|label:references:]
>
> * [API Token Authentication Documentation](https://wiki.resolution.de/doc/api-token-authentication/latest)
> * [API Token Authentication Documentation - Rest API](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api)

* [list all tokens](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-Listalltokens)

  > \[!NOTE]
  >
  > * to list all tokens for single user:
  >
  >   ```bash
  >   $ curl -v -XGET \
  >          https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/ |
  >     jq -r
  >   ```
  > * to list tokens for all users:
  >
  >   ```bash
  >   $ curl -v \
  >          -X GET \
  >          https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter |
  >     jq -r
  >   ```

  ```bash
  $ curl -s -D- \
         -XGET \
         -H "Content-Type: application/json"  \
         https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
    sed '/^\s*$/,$!d;//d' |
    jq -r
  ```

  * get id, created, last access, and valid timestamp

    ```bash
    function epoch2timestamp() {
      [[ 0 != $1 ]] && echo $(date -d @$(( $1/1000 )) +%FT%T.%3N%Z) || echo "0";
    }

    $ while read -r _id _created _lastAccess _validUntil; do
        echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
      done < <( curl -s -D- \
                     -XGET \
                     -H "Content-Type: application/json" \
                     https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
                sed '/^\s*$/,$!d;//d' |
                jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
              ) |
      column -t
    537  2024-01-31T21:32:51.000PST  2024-03-26T23:30:30.000PDT  2024-07-31T21:32:51.000PDT
    579  2024-03-26T23:19:16.000PDT  0                           2024-09-26T23:19:16.000PDT

    # with header
    $ ( echo "ID CREATED LASTACCESS VALIDUNTIL";
        while read -r _id _created _lastAccess _validUntil; do
          echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
        done < <( curl -s -D- \
                       -XGET \
                       -H "Content-Type: application/json" \
                       https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
                  sed '/^\s*$/,$!d;//d' |
                  jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
                )
      ) | column -t
    ID   CREATED                     LASTACCESS                  VALIDUNTIL
    537  2024-01-31T21:32:51.000PST  2024-03-26T23:33:33.000PDT  2024-07-31T21:32:51.000PDT
    579  2024-03-26T23:19:16.000PDT  0                           2024-09-26T23:19:16.000PDT
    ```

    * or

      ```bash
      $ curl -s -D- \
             -XGET \
             -H "Content-Type: application/json" \
             https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
        sed '/^\s*$/,$!d;//d' |
        jq -r '.content[] | [ .created, .lastAccessed, .validUntil ] | join("\n")' |
        xargs -r -I{} bash -c "et=\"{}\"; date -d @\$(( \${et}/1000 )) +%c"
      Mon 18 Dec 2023 10:25:58 AM PST
      Tue 26 Mar 2024 10:21:30 PM PDT
      Tue 18 Jun 2024 10:25:58 AM PDT

      # or
      $ while read -r _d; do
          date -d @$(( ${_d}/1000 )) +%c;
        done < <( curl -s -D- \
                       -XGET \
                       -H "Content-Type: application/json" \
                       https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
                  sed '/^\s*$/,$!d;//d' |
                  jq -r '.content[] | [ .created, .lastAccessed, .validUntil ] | join("\n")'
                )
      Mon 18 Dec 2023 10:25:58 AM PST
      Tue 26 Mar 2024 10:14:58 PM PDT
      Tue 18 Jun 2024 10:25:58 AM PDT
      ```
* [create token](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-Createanewtoken)

  > \[!TIP]
  >
  > * expiration keywords
  >   * `tokenValidityTimeInMonths`
  >   * `tokenExpirationDateTime`
  >   * `tokenExpirationDateTimeMillis`

  ```bash
  $ curl -v -d '{"tokenDescription":"<token-description>"}' \
         -X POST \
         --header "Content-Type: application/json" \
         https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
  ```

  * create new token with expiration time

    > \[!NOTE|label:references:]
    >
    > * with `tokenValidityTimeInMonths`
    >
    >   ```bash
    >   $ curl -v \
    >          -d '{"tokenDescription":"<token-description>", "tokenValidityTimeInMonths" : 1}' \
    >          -X POST \
    >          --header "Content-Type: application/json" \
    >          https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
    >   ```
    > * with `tokenExpirationDateTime`
    >
    >   ```bash
    >   $ curl -v \
    >          -d '{"tokenDescription":"Custom expiration", "tokenExpirationDateTime" : "2020-10-19T10:29:00.000+02:00"}' \
    >          -X POST \
    >          --header "Content-Type: application/json" \
    >          https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
    >   ```

    ```bash
    $ curl -s \
           -d '{"tokenDescription":"marslo-token-api-test", "tokenValidityTimeInMonths" : 6}' \
           -X POST \
           --header "Content-Type: application/json" \
           https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
     jq -r .plainTextToken
    NdxEToKfDsjUE7tct1ePP6erE1xdDsEAa64BOT
    ```
  * [create token for another users](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-CreateTokensforotherUsers)

    ```bash
    $ curl -v \
           -d '{"tokenDescription":"token for another user", "tokenForUserKey":"JIRAUSER10105"}' \
           POST \
           --header "Content-Type: application/json" \
           https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token

    # or with token validity time
    $ curl -v \
           -d '{"tokenDescription":"token for another user", "tokenForUserKey":"JIRAUSER10105","tokenValidityTimeInMonths":12}' \
           POST \
           --header "Content-Type: application/json" \
           https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
    ```
* [update token description](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-Updateatokendescription)

  ```bash
  $ curl -v \
         -d '{"tokenDescription":"Updated token description"}' \
         -X PATCH \
         --header "Content-Type: application/json" \
         https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/<token-id>
  ```
* [delete token](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-Deleteatoken)

  > \[!NOTE|label:references:]
  >
  > ```bash
  > $ curl -v \
  >        -X DELETE \
  >        https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/<token-id>
  > ```

  ```bash
  # list before token deleted
  $ ( echo "ID CREATED LASTACCESS VALIDUNTIL";
      while read -r _id _created _lastAccess _validUntil; do
        echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
      done < <( curl -s -D- \
                     -XGET \
                     -H "Content-Type: application/json" \
                     https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
                sed '/^\s*$/,$!d;//d' |
                jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
              )
    ) | column -t
  ID   CREATED                     LASTACCESS                  VALIDUNTIL
  537  2024-01-31T21:32:51.000PST  2024-03-26T23:40:02.000PDT  2024-07-31T21:32:51.000PDT
  579  2024-03-26T23:19:16.000PDT  0                           2024-09-26T23:19:16.000PDT
  580  2024-03-26T23:36:02.000PDT  0                           2024-09-26T23:36:02.000PDT
  581  2024-03-26T23:36:11.000PDT  0                           2024-09-26T23:36:11.000PDT

  # delete
  $ curl -s -D- \
         -X DELETE \
         https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token/581
  HTTP/2 200
  date: Wed, 27 Mar 2024 06:41:06 GMT
  content-type: application/json;charset=UTF-8
  x-arequestid: 1421x248002x2
  x-anodeid: jiraprod5
  referrer-policy: strict-origin-when-cross-origin
  x-xss-protection: 1; mode=block
  x-content-type-options: nosniff
  x-frame-options: SAMEORIGIN
  content-security-policy: sandbox
  strict-transport-security: max-age=31536000
  set-cookie: JSESSIONID=731380C1F17B2F9A59E211B0442AAFFB; Path=/; Secure; HttpOnly
  x-seraph-loginreason: OK
  set-cookie: atlassian.xsrf.token=A8KN-1NAU-M55V-EQSR_1811ae8601112c05430589e686032924599718c9_lin; Path=/; Secure; SameSite=None
  x-asessionid: k5q153
  x-ausername: marslo
  cache-control: no-cache, no-store, no-transform

  true

  # curl without header
  $ curl -s \
         -X DELETE \
         https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token/580
  true

  # verify
  $ ( echo "ID CREATED LASTACCESS VALIDUNTIL";
      while read -r _id _created _lastAccess _validUntil; do
        echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})";
      done < <( curl -s -D- \
                     -XGET \
                     -H "Content-Type: application/json" \
                     https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token |
                sed '/^\s*$/,$!d;//d' |
                jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )'
              )
    ) | column -t
  ID   CREATED                     LASTACCESS                  VALIDUNTIL
  537  2024-01-31T21:32:51.000PST  2024-03-26T23:44:32.000PDT  2024-07-31T21:32:51.000PDT
  579  2024-03-26T23:19:16.000PDT  0                           2024-09-26T23:19:16.000PDT
  ```

  * [delete all tokens for a user](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-Deletealltokensforauser)

    ```bash
    $ curl GET \
           https://jira.sample.com/rest/api/2/user?username=some.username |
       jq -r
    ```
* [filter](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-Filterparameters)

| PARAMETER            | VALUE                | COMMENT                                                                                                                                                                                 |
| -------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `userFilter`         | valid user key       | <p>read above how to get a user key for a name or by email address;<br>if you want to filter for more than one user, repeat that parameter for as many users you want to filter for</p> |
| `descriptionFilter`  | search term          | string to search for in all token descriptions                                                                                                                                          |
| `notValidAfter`      | epoch Unix timestamp | tokens not valid anymore after that date/ time in milliseconds                                                                                                                          |
| `tokenScope`         | integer              | 0 = no scope (all pre 1.5.0 tokens), 1 = read-only, 2 = read/ write                                                                                                                     |
| `fromCreated`        | epoch Unix timestamp | -                                                                                                                                                                                       |
| `untilCreated`       | epoch Unix timestamp | -                                                                                                                                                                                       |
| `fromLastUsed`       | epoch Unix timestamp | -                                                                                                                                                                                       |
| `untilLastUsed`      | epoch Unix timestamp | -                                                                                                                                                                                       |
| `fromExpiresDuring`  | epoch Unix timestamp | -                                                                                                                                                                                       |
| `untilExpiresDuring` | epoch Unix timestamp | -                                                                                                                                                                                       |

* [list token expired after certain time](https://wiki.resolution.de/doc/api-token-authentication/latest/admin-guide/rest-api#id-.RESTAPIv2.5.x-Retrievealltokensnotvalidafteracertaintime)

  ```bash
  $ curl "https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter?notValidAfter=1688918956972" |
    jq -r

  # with limit and page
  $ curl "https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter?page=0&limit=1&notValidAfter=1688918956972" |
    jq -r
  ```

#### [generate OAuth consumer](https://developer.atlassian.com/cloud/jira/platform/jira-rest-api-oauth-authentication/)

> \[!NOTE|label:references:]
>
> * [OAuth 1.0a for REST APIs (Deprecated)](https://developer.atlassian.com/cloud/jira/platform/jira-rest-api-oauth-authentication/)
> * [atlassian-oauth-examples](https://bitbucket.org/atlassianlabs/atlassian-oauth-examples/src/master/)

```bash
$ openssl genrsa -out jira_privatekey.pem 1024
$ openssl req -newkey rsa:1024 -x509 -key jira_privatekey.pem -out jira_publickey.cer -days 365
$ openssl pkcs8 -topk8 -nocrypt -in jira_privatekey.pem -out jira_privatekey.pcks8
$ openssl x509 -pubkey -noout -in jira_publickey.cer  > jira_publickey.pem
```

#### icons and priority

**priority**

> \[!NOTE|label:references:]
>
> * [how do I view ALL icons for priority](https://community.atlassian.com/t5/Jira-questions/how-do-I-view-ALL-icons-for-priority/qaq-p/802188)
> * [AlexanderBartash/JIRA-Priority-Icons](https://github.com/AlexanderBartash/JIRA-Priority-Icons)
> * [DevOps Use case: Jira Jenkins Integration](https://medium.com/@shrut_terminator/devops-usecase-jira-jenkins-integration-4051413446a9)

```bash
$ for _i in "blocker.png" "blocker.svg" "critical.png" "critical.svg" "high.png" "high.svg" "highest.png" "highest.svg" "low.png" "low.svg" "lowest.png" "lowest.svg" "major.png" "major.svg" "medium.png" "medium.svg" "minor.png" "minor.svg" "trivial.png" "trivial.svg"; do
    echo "--> ${_i}"
    curl -O https://jira-trigger-plugin.atlassian.net/images/icons/priorities/${_i}
  done
```

### confluence

```bash
$ confluenceName='confluence.domain.com'
$ pageID='143765713'
```

> get page id: ![confluence page id](https://4276369325-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpuTw6o3ALq0J3Uf7ELc7%2Fuploads%2Fgit-blob-a83a79bcae9d2117b4f6650498e3cf0b0222ef1e%2Fconfluence-pageid.png?alt=media)

#### [myself](https://wiki.resolution.de/doc/api-token-authentication/latest/user-guide/using-tokens-examples#id-.UsingTokensExamplesv1.7.0-Confluence)

```bash
$ curl -s https://${confluenceName}/rest/api/user/current | jq -r
```

#### get info

```bash
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq --raw-output
```

* get space

  ```bash
  $ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .space.key
  ```
* get title

  ```bash
  $ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .title
  ```
* get page history

  ```bash
  $ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .version.number
  ```

  * get next version

    ```bash
    currentVer=$(curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .version.number)
    newVer=$((currentVer+1))
    ```

#### publish to confluence

> \[!NOTE|label:references:]
>
> * [sample script](https://raw.githubusercontent.com/marslo/mytools/master/itool/confluencePublisher.sh)

```bash
$ url="https://${confluenceName}/rest/api/content/${pageID}"
$ page=$(curl -s ${url})
$ space=$(echo "${page}" | jq .space.key)
$ title=$(echo "${page}" | jq .title)
$ currentVer=$(echo "${page}" | jq .version.number)
$ newVer=$((currentVer+1))

$ cat > a.json << EOF
{
  "id": "${pageID}",
  "type": "page",
  "title": ${title},
  "space": {"key": ${space}},
  "body": {
    "storage": {
      "value": "<h1>Hi confluence</h1>",
      "representation": "storage"
    }
  },
  "version": {"number":${newVer}}
}
EOF

$ curl -s \
       -i \
       -X PUT \
       -H 'Content-Type: application/json' \
       --data "$(cat a.json)" \
       https://${confluenceName}/rest/api/content/${pageID}
```

* result ![publish via api](https://4276369325-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpuTw6o3ALq0J3Uf7ELc7%2Fuploads%2Fgit-blob-178406ab58a822f90189a6c7fd660efe0a6d5f3d%2Fpublish-to-confluence.png?alt=media)

#### plugins

[**Multiexcerpt**](https://marketplace.atlassian.com/apps/169/multiexcerpt?tab=overview\&hosting=cloud)

* create excerpt ![create multiexcerpt](https://4276369325-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpuTw6o3ALq0J3Uf7ELc7%2Fuploads%2Fgit-blob-a6fce4419ec10875d6d515fe67e160b009a4f905%2Fjira-plugin-Multiexcerpt-create.png?alt=media)
* include excerpt ![include excerpt](https://4276369325-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpuTw6o3ALq0J3Uf7ELc7%2Fuploads%2Fgit-blob-2aa0a813dc3e56171c6884b95c996a0d62df4576%2Fjira-plugin-Multiexcerpt-include-setting.png?alt=media)
* result ![include excerpt](https://4276369325-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpuTw6o3ALq0J3Uf7ELc7%2Fuploads%2Fgit-blob-d5414b92d8dfc7743c3fd7f7b18a6377bd37eb80%2Fjira-plugin-Multiexcerpt-include-result.png?alt=media)

#### insert svg

[**HTML Macro**](https://confluence.atlassian.com/conf719/html-macro-1157466770.html)

* insert svg image

  > \[!TIP|label:get svg image:]
  >
  > * `...` -> `Attachments`
  > * preview the image and get info from URL : `...&preview=/506105287/513281481/k8s-ha-cluster-stacked-etcd.v3.svg`

  ```html
  <img width="800" src="https://ewiki.sample.com/download/attachments/506105287/513281481/k8s-ha-cluster-stacked-etcd.v3.svg">
  ```

**edit source via**

> \[!TIP|label:references:]
>
> * [CONFCLOUD-40672: Confluence File Preview does not allow setting custom size for SVG format](https://jira.atlassian.com/browse/CONFCLOUD-40672?focusedId=1232690\&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-1232690)

```html
<p><ac:image ac:width="301"><ri:attachment ri:filename="SVG_logo.svg" /></ac:image></p>
```

### CLI

> \[!NOTE|label:references:]
>
> * [acli: Appfire CLI](https://appfire.atlassian.net/wiki/spaces/ACLI/pages/60559862/Get+Started)
>   * [acli download](https://appfire.atlassian.net/wiki/spaces/ACLI/pages/60560924/CLI+Client+Installation+and+Use)
>     * [windows amd64: ACLI-11.3.0-amd64-installer.exe](https://appfire.atlassian.net/wiki/download/attachments/60562669/ACLI-11.3.0-amd64-installer.exe?api=v2)
>     * [linux amd64: ACLI-11.3.0-amd64-installer.run](https://appfire.atlassian.net/wiki/download/attachments/60562669/ACLI-11.3.0-amd64-installer.run?api=v2)
>     * [macos amd64: ACLI-11.3.0-amd64-installer.dmg](https://appfire.atlassian.net/wiki/download/attachments/60562669/ACLI-11.3.0-amd64-installer.dmg?api=v2)
>     * [macos arm64: ACLI-11.3.0-arm64-installer.dmg](https://appfire.atlassian.net/wiki/download/attachments/60562669/ACLI-11.3.0-arm64-installer.dmg?api=v2)\\
>     * [docker image](https://appfire.atlassian.net/wiki/spaces/ACLI/pages/60559294/Docker+Images+for+ACLI)
>   * [Action Examples](https://appfire.atlassian.net/wiki/spaces/ACLI/pages/60562181/Action+Examples)
>     * [Action Examples - acli help using](https://appfire.atlassian.net/wiki/spaces/ACLI/pages/60563920/Action+Examples+-+acli+help+using)

#### running with docker images

```bash
$ $ docker run -ti bobswiftapps/acli:latest acli -a getClientInfo
# or
$ docker run -ti bobswiftapps/acli:latest /bin/bash
bash-4.4# acli -a getClientInfo

# with env
$ cat .env
examplegear=jira -s https://examplegear.atlassian.net -u anonymous
examplegear_confluence=confluence -s https://examplegear.atlassian.net/wiki -u anonymous
$ docker run --env-file=.env -ti bobswiftapps/acli:latest /bin/bash
bash-5.0# acli $examplegear -a getServerInfo
# or
docker run -e examplegear='jira -s https://examplegear.atlassian.net -u anonymous' -ti bobswiftapps/acli:latest /bin/bash
bash-4.4# acli ${examplegear} -a getServerInfo

# with acli.properties
$ docker run -v ${PWD}/acli.properties:/opt/acli/acli.properties \
         -ti bobswiftapps/acli:latest
# or prior to version 11.0.0, use:
$ docker run -v ${PWD}/acli.properties:/opt/atlassian-cli/acli.properties \
         -ti bobswiftapps/acli:latest
# or with `ACLI_CONFIG` env
$ docker run -v ${PWD}/acli.properties:/tmp/acli.properties \
         -e ACLI_CONFIG=/tmp/acli.properties \
         -ti bobswiftapps/acli:latest \
         acli -a getServerInfo --outputFormat 2
```

#### [create .acli.keystore](https://appfire.atlassian.net/wiki/spaces/SUPPORT/pages/349962465/How+to+use+Secure+Properties)

```bash
$ acli system setSecureProperty --name my.secret --secret -
Enter secure value: <secret value prompt>
Secure properties file does not yet exist. Creating...
Enter new secure properties password: <new password prompt>
Confirm secure properties password: <new password prompt>
Secure properties file created.
Value for key 'foo' set in secure properties file.
```

#### [acli.properties](https://appfire.atlassian.net/wiki/spaces/SUPPORT/pages/349962465/How+to+use+Secure+Properties#Referencing-secrets-in-acli.properties)
