Initial
parent
7f6426594e
commit
0e63e463c4
|
@ -0,0 +1,5 @@
|
||||||
|
/.settings
|
||||||
|
/.vscode
|
||||||
|
/target
|
||||||
|
/.classpath
|
||||||
|
/.project
|
|
@ -0,0 +1,26 @@
|
||||||
|
Copyright (c) 2018, ASERVO Software GmbH
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of ASERVO Software GmbH nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
280
README.md
280
README.md
|
@ -1,2 +1,280 @@
|
||||||
# jira-rest-extender
|
[](https://www.tiburon.su)
|
||||||
|
|
||||||
|
REST API Extender for JIRA
|
||||||
|
================
|
||||||
|
|
||||||
|
REST API for automated JIRA configuration with URMS
|
||||||
|
|
||||||
|
Related Documentation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* [Atlassian REST API design guidelines version 1](https://developer.atlassian.com/server/framework/atlassian-sdk/atlassian-rest-api-design-guidelines-version-1/)
|
||||||
|
|
||||||
|
Resources
|
||||||
|
---------
|
||||||
|
|
||||||
|
All resources produce JSON (media type: `application/json`) results.
|
||||||
|
|
||||||
|
### Settings
|
||||||
|
|
||||||
|
Access important JIRA settings like the title, the base url, the mode
|
||||||
|
etc.
|
||||||
|
|
||||||
|
* #### `GET /rest/extender/1/settings`
|
||||||
|
|
||||||
|
Get JIRA application settings.
|
||||||
|
|
||||||
|
__Responses__
|
||||||
|
|
||||||
|
![Status 200][status-200]
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"baseurl": "http://localhost:2990/jira",
|
||||||
|
"mode": "private",
|
||||||
|
"title": "Your Company JIRA"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
![Status 401][status-401]
|
||||||
|
|
||||||
|
Returned if the current user is not authenticated.
|
||||||
|
|
||||||
|
![Status 403][status-403]
|
||||||
|
|
||||||
|
Returned if the current user is not an administrator.
|
||||||
|
|
||||||
|
* #### `PUT /rest/extender/1/settings`
|
||||||
|
|
||||||
|
Set JIRA application settings.
|
||||||
|
|
||||||
|
__Request Body__
|
||||||
|
|
||||||
|
Media type: `application/json`
|
||||||
|
|
||||||
|
Content: Settings, for example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"baseurl": "http://localhost:2990/jira",
|
||||||
|
"mode": "private",
|
||||||
|
"title": "Your Company JIRA"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
__Request Parameters__
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
__Responses__
|
||||||
|
|
||||||
|
![Status 200][status-200]
|
||||||
|
|
||||||
|
Returned if request could be executed without major exceptions.
|
||||||
|
|
||||||
|
The response will contain a list of errors that occurred while setting
|
||||||
|
some specific values such as a string that was too long, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"errorMessages": [
|
||||||
|
"The length of the application title must not exceed 255 characters"
|
||||||
|
],
|
||||||
|
"errors": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
![Status 401][status-401]
|
||||||
|
|
||||||
|
Returned if the current user is not authenticated.
|
||||||
|
|
||||||
|
![Status 403][status-403]
|
||||||
|
|
||||||
|
Returned if the current user is not an administrator.
|
||||||
|
|
||||||
|
### Licenses
|
||||||
|
|
||||||
|
The JIRA license API is a bit weird and needs to be well understood.
|
||||||
|
Just like in the web interface, different license keys can theoretically
|
||||||
|
be set for each application (JIRA Core, JIRA Software, etc.). However,
|
||||||
|
the entered license key is always set for all applications for which it
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
1. JIRA Core and JIRA Software each have their own license key. If a
|
||||||
|
license key is now entered (in the web interface or via the REST API)
|
||||||
|
with which both applications can be licensed, this license key is stored
|
||||||
|
for both applications.
|
||||||
|
|
||||||
|
2. JIRA Core and JIRA Software use a common license key. If a license
|
||||||
|
key is now entered (in the web interface or via the REST API) with which
|
||||||
|
only JIRA Core can be licensed, the license key is also only stored for
|
||||||
|
JIRA Core.
|
||||||
|
|
||||||
|
So again, an entered license key is always stored for all applications
|
||||||
|
for which it is valid. The web interface might suggest that you can
|
||||||
|
select the desired application, but this is not true.
|
||||||
|
|
||||||
|
* #### `GET /rest/extender/1/licenses`
|
||||||
|
|
||||||
|
Get the license keys together with the application keys of the
|
||||||
|
applications using this license key.
|
||||||
|
|
||||||
|
__Responses__
|
||||||
|
|
||||||
|
![Status 200][status-200]
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"key": "AAA...",
|
||||||
|
"applicationKeys": [
|
||||||
|
"jira-software"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "AAA...",
|
||||||
|
"applicationKeys": [
|
||||||
|
"jira-core",
|
||||||
|
"jira-servicedesk"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
![Status 401][status-401]
|
||||||
|
|
||||||
|
Returned if the current user is not authenticated.
|
||||||
|
|
||||||
|
![Status 403][status-403]
|
||||||
|
|
||||||
|
Returned if the current user is not an administrator.
|
||||||
|
|
||||||
|
* #### `PUT /rest/extender/1/licenses`
|
||||||
|
|
||||||
|
Set a license by its license key.
|
||||||
|
|
||||||
|
__Request Body__
|
||||||
|
|
||||||
|
Media type: `text/plain`
|
||||||
|
|
||||||
|
Content: License key, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
AAA...
|
||||||
|
```
|
||||||
|
|
||||||
|
__Request Parameters__
|
||||||
|
|
||||||
|
| parameter | type | description |
|
||||||
|
| ----------- | --------- | ------------------------------------------------------------------------------ |
|
||||||
|
| `clear` | _boolean_ | Clear all licenses before setting the new license, optional, defaults to false |
|
||||||
|
|
||||||
|
__Responses__
|
||||||
|
|
||||||
|
![Status 200][status-200]
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"key": "AAA...",
|
||||||
|
"applicationKeys": [
|
||||||
|
"jira-core",
|
||||||
|
"jira-servicedesk",
|
||||||
|
"jira-software"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
![Status 401][status-401]
|
||||||
|
|
||||||
|
Returned if the current user is not authenticated.
|
||||||
|
|
||||||
|
![Status 403][status-403]
|
||||||
|
|
||||||
|
Returned if the current user is not an administrator.
|
||||||
|
|
||||||
|
### Syncronise Crowd User Directory
|
||||||
|
|
||||||
|
* #### `GET /rest/extender/1/directory`
|
||||||
|
|
||||||
|
Get info about User Directories.
|
||||||
|
|
||||||
|
__Responses__
|
||||||
|
|
||||||
|
![Status 200][status-200]
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Jira Internal Directory",
|
||||||
|
"active": true,
|
||||||
|
"createdDate": 1362038271308,
|
||||||
|
"updatedDate": 1362038271308,
|
||||||
|
"lowerName": "jira internal directory",
|
||||||
|
"description": "Jira default internal directory",
|
||||||
|
"type": "INTERNAL",
|
||||||
|
"implementationClass": "com.atlassian.crowd.directory.InternalDirectory",
|
||||||
|
"lowerImplementationClass": "com.atlassian.crowd.directory.internaldirectory",
|
||||||
|
"allowedOperations":["CREATE_GROUP", "CREATE_ROLE", "CREATE_USER", "DELETE_GROUP", "DELETE_ROLE", "DELETE_USER", "UPDATE_GROUP",…],
|
||||||
|
"attributes":{
|
||||||
|
"user_encryption_method": "atlassian-security"
|
||||||
|
},
|
||||||
|
"empty": false,
|
||||||
|
"keys":["user_encryption_method"],
|
||||||
|
"encryptionType": "atlassian-security"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
![Status 401][status-401]
|
||||||
|
|
||||||
|
Returned if the current user is not authenticated.
|
||||||
|
|
||||||
|
![Status 403][status-403]
|
||||||
|
|
||||||
|
Returned if the current user is not an administrator.
|
||||||
|
|
||||||
|
* #### `PUT /rest/extender/1/directory`
|
||||||
|
|
||||||
|
Start sycronyse User Directory.
|
||||||
|
|
||||||
|
__Request Parameters__
|
||||||
|
|
||||||
|
| parameter | type | description |
|
||||||
|
| --------- | ------ | ----------------------------------------------------- |
|
||||||
|
| `id` | _long_ | id of the User Directory, which should be syncronised |
|
||||||
|
|
||||||
|
__Responses__
|
||||||
|
|
||||||
|
![Status 200][status-200]
|
||||||
|
|
||||||
|
Returned if request could be executed without major exceptions.
|
||||||
|
|
||||||
|
The response will contain a list of errors that occurred while setting
|
||||||
|
some specific values such as a string that was too long, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"message": "parameter should not be null!",
|
||||||
|
"status-code": 500,
|
||||||
|
"stack-trace": full_stack_trace_of_the_application
|
||||||
|
}
|
||||||
|
```
|
||||||
|
![Status 401][status-401]
|
||||||
|
|
||||||
|
Returned if the current user is not authenticated.
|
||||||
|
|
||||||
|
![Status 403][status-403]
|
||||||
|
|
||||||
|
Returned if the current user is not an administrator.
|
||||||
|
|
||||||
|
|
||||||
|
[status-200]: https://img.shields.io/badge/status-200-brightgreen.svg
|
||||||
|
[status-400]: https://img.shields.io/badge/status-400-red.svg
|
||||||
|
[status-401]: https://img.shields.io/badge/status-401-red.svg
|
||||||
|
[status-403]: https://img.shields.io/badge/status-403-red.svg
|
||||||
|
[status-404]: https://img.shields.io/badge/status-404-red.svg
|
||||||
|
|
|
@ -0,0 +1,533 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>su.tiburon.atlassian.jira</groupId>
|
||||||
|
<artifactId>rest-extender</artifactId>
|
||||||
|
<version>1.1.0</version>
|
||||||
|
<packaging>atlassian-plugin</packaging>
|
||||||
|
|
||||||
|
<name>REST API extender for JIRA</name>
|
||||||
|
<description>REST API extender for JIRA.</description>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>BSD 3-Clause License</name>
|
||||||
|
<url>https://opensource.org/licenses/BSD-3-Clause</url>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<issueManagement>
|
||||||
|
<system>Github</system>
|
||||||
|
<url>https://github.com/tiburon-777/rest-extender/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:git://github.com/tiburon-777/rest-extender.git</connection>
|
||||||
|
<developerConnection>scm:git:git@github.com:tiburon-777/rest-extender.git</developerConnection>
|
||||||
|
<url>https://github.com/tiburon-777/rest-extender</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<organization>
|
||||||
|
<name>OCTOPUS CodeWare</name>
|
||||||
|
<url>http://www.tiburon.su/</url>
|
||||||
|
</organization>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>Andrey Ivanov</name>
|
||||||
|
<email>ya@tiburon.su</email>
|
||||||
|
<organization>OCTOPUS CodeWare</organization>
|
||||||
|
<organizationUrl>https://www.tiburon.su</organizationUrl>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- General properties -->
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
|
||||||
|
<!-- Atlassian properties -->
|
||||||
|
<jira.version>8.0.1</jira.version>
|
||||||
|
<!-- Be careful with changing the data version -->
|
||||||
|
<jira.data.version>7.5.0</jira.data.version>
|
||||||
|
<atlassian.amps.version>8.0.2</atlassian.amps.version>
|
||||||
|
<amps.version>8.0.2</amps.version>
|
||||||
|
<atlassian.project.templates.version>6.2.0</atlassian.project.templates.version>
|
||||||
|
<atlassian.sal.version>3.1.0</atlassian.sal.version>
|
||||||
|
<atlassian.plugins.rest.version>5.0.1</atlassian.plugins.rest.version>
|
||||||
|
<atlassian.quick.reload.version>2.0.0</atlassian.quick.reload.version>
|
||||||
|
<atlassian.spring.scanner.version>2.1.5</atlassian.spring.scanner.version>
|
||||||
|
<atlassian.crowdapi.version>2.10.2-rc04</atlassian.crowdapi.version>
|
||||||
|
<upm.license.compatibility.version>2.15.3</upm.license.compatibility.version>
|
||||||
|
|
||||||
|
<!-- Other properties -->
|
||||||
|
<slf4j.version>1.7.9</slf4j.version>
|
||||||
|
<javax.servlet.version>2.4</javax.servlet.version>
|
||||||
|
<javax.ws.version>1.1.1</javax.ws.version>
|
||||||
|
<javax.xml.version>2.1</javax.xml.version>
|
||||||
|
|
||||||
|
<!-- Test properties -->
|
||||||
|
<junit.version>4.12</junit.version>
|
||||||
|
<mockito.version>1.10.19</mockito.version>
|
||||||
|
<jacoco.version>0.8.1</jacoco.version>
|
||||||
|
<coveralls.version>4.3.0</coveralls.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Atlassian dependencies -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.jira</groupId>
|
||||||
|
<artifactId>jira-api</artifactId>
|
||||||
|
<version>${jira.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>jta</groupId>
|
||||||
|
<artifactId>jta</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.jira</groupId>
|
||||||
|
<artifactId>jira-core</artifactId>
|
||||||
|
<version>${jira.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>jndi</groupId>
|
||||||
|
<artifactId>jndi</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>jta</groupId>
|
||||||
|
<artifactId>jta</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.jira.plugins</groupId>
|
||||||
|
<artifactId>project-templates-api</artifactId>
|
||||||
|
<version>${atlassian.project.templates.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.jira</groupId>
|
||||||
|
<artifactId>jira-rest-api</artifactId>
|
||||||
|
<version>${jira.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.plugins.rest</groupId>
|
||||||
|
<artifactId>atlassian-rest-common</artifactId>
|
||||||
|
<version>${atlassian.plugins.rest.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.plugins.rest</groupId>
|
||||||
|
<artifactId>atlassian-rest-doclet</artifactId>
|
||||||
|
<version>${atlassian.plugins.rest.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.plugin</groupId>
|
||||||
|
<artifactId>atlassian-spring-scanner-annotation</artifactId>
|
||||||
|
<version>${atlassian.spring.scanner.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.templaterenderer</groupId>
|
||||||
|
<artifactId>atlassian-template-renderer-api</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.sal</groupId>
|
||||||
|
<artifactId>sal-api</artifactId>
|
||||||
|
<version>${atlassian.sal.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.crowd</groupId>
|
||||||
|
<artifactId>crowd-api</artifactId>
|
||||||
|
<version>${atlassian.crowdapi.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.upm</groupId>
|
||||||
|
<artifactId>plugin-license-storage-lib</artifactId>
|
||||||
|
<version>${upm.license.compatibility.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.upm</groupId>
|
||||||
|
<artifactId>plugin-license-storage-plugin</artifactId>
|
||||||
|
<version>${upm.license.compatibility.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.upm</groupId>
|
||||||
|
<artifactId>licensing-api</artifactId>
|
||||||
|
<version>${upm.license.compatibility.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.upm</groupId>
|
||||||
|
<artifactId>upm-api</artifactId>
|
||||||
|
<version>${upm.license.compatibility.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Other dependencies -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>${slf4j.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.ws.rs</groupId>
|
||||||
|
<artifactId>jsr311-api</artifactId>
|
||||||
|
<version>${javax.ws.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-api</artifactId>
|
||||||
|
<version>${javax.xml.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test dependencies -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.atlassian.jira</groupId>
|
||||||
|
<artifactId>jira-tests</artifactId>
|
||||||
|
<version>${jira.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.atlassian.maven.plugins</groupId>
|
||||||
|
<artifactId>jira-maven-plugin</artifactId>
|
||||||
|
<version>${atlassian.amps.version}</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<productVersion>${jira.version}</productVersion>
|
||||||
|
<enableFastdev>false</enableFastdev>
|
||||||
|
<enableDevToolbox>false</enableDevToolbox>
|
||||||
|
<enablePde>false</enablePde>
|
||||||
|
<!-- <extractDependencies>false</extractDependencies> -->
|
||||||
|
<skipRestDocGeneration>true</skipRestDocGeneration>
|
||||||
|
<skipManifestValidation>true</skipManifestValidation>
|
||||||
|
<allowGoogleTracking>false</allowGoogleTracking>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<atlassian.mail.senddisabled>false</atlassian.mail.senddisabled>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
<applications>
|
||||||
|
<application>
|
||||||
|
<applicationKey>jira-software</applicationKey>
|
||||||
|
<version>${jira.version}</version>
|
||||||
|
</application>
|
||||||
|
</applications>
|
||||||
|
<pluginArtifacts>
|
||||||
|
<pluginArtifact>
|
||||||
|
<groupId>com.atlassian.labs.plugins</groupId>
|
||||||
|
<artifactId>quickreload</artifactId>
|
||||||
|
<version>${atlassian.quick.reload.version}</version>
|
||||||
|
</pluginArtifact>
|
||||||
|
</pluginArtifacts>
|
||||||
|
<instructions>
|
||||||
|
<Atlassian-Plugin-Key>${project.groupId}.${project.artifactId}</Atlassian-Plugin-Key>
|
||||||
|
<Spring-Context>*</Spring-Context>
|
||||||
|
<Import-Package>
|
||||||
|
org.springframework.*;resolution:="optional",
|
||||||
|
org.eclipse.gemini.*;resolution:="optional",
|
||||||
|
sun.misc;resolution:=optional,
|
||||||
|
*
|
||||||
|
</Import-Package>
|
||||||
|
<Export-Package/>
|
||||||
|
</instructions>
|
||||||
|
<products>
|
||||||
|
<product>
|
||||||
|
<id>crowd</id>
|
||||||
|
<instanceId>crowd</instanceId>
|
||||||
|
<version>3.1.3</version>
|
||||||
|
</product>
|
||||||
|
<product>
|
||||||
|
<id>confluence</id>
|
||||||
|
<instanceId>confluence</instanceId>
|
||||||
|
<version>6.8.0</version>
|
||||||
|
</product>
|
||||||
|
</products>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.atlassian.plugin</groupId>
|
||||||
|
<artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
|
||||||
|
<version>${atlassian.spring.scanner.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>atlassian-spring-scanner</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>process-classes</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<version>${jacoco.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>prepare-agent</id>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>report</id>
|
||||||
|
<phase>test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>report</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.eluder.coveralls</groupId>
|
||||||
|
<artifactId>coveralls-maven-plugin</artifactId>
|
||||||
|
<version>${coveralls.version}</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>sonatype-nexus-snapshots</id>
|
||||||
|
<name>Sonatype Nexus snapshot repository</name>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>sonatype-nexus-staging</id>
|
||||||
|
<name>Sonatype Nexus release staging repository</name>
|
||||||
|
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>release</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
|
<version>1.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>sign-artifacts</id>
|
||||||
|
<phase>deploy</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>sign</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<keyname>${gpg.keyname}</keyname>
|
||||||
|
<passphrase>${gpg.passphrase}</passphrase>
|
||||||
|
<executable>${gpg.executable}</executable>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>2.8.2</version>
|
||||||
|
<configuration>
|
||||||
|
<!-- Deployment is already handled by nexus-staging-maven-plugin -->
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
|
<version>1.6.8</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>default-deploy</id>
|
||||||
|
<phase>deploy</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>deploy</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<serverId>sonatype-nexus-staging</serverId>
|
||||||
|
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||||
|
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>sources</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>javadoc</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>atlassian-public</id>
|
||||||
|
<url>https://packages.atlassian.com/maven/repository/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<updatePolicy>never</updatePolicy>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>sonatype-oss</id>
|
||||||
|
<url>https://oss.sonatype.org/content/groups/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<updatePolicy>never</updatePolicy>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>atlassian-public</id>
|
||||||
|
<url>https://packages.atlassian.com/maven/repository/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<updatePolicy>never</updatePolicy>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</releases>
|
||||||
|
</pluginRepository>
|
||||||
|
|
||||||
|
<pluginRepository>
|
||||||
|
<id>sonatype-oss</id>
|
||||||
|
<url>https://oss.sonatype.org/content/groups/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<updatePolicy>never</updatePolicy>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<checksumPolicy>warn</checksumPolicy>
|
||||||
|
</releases>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,160 @@
|
||||||
|
package su.tiburon.atlassian.jira;
|
||||||
|
|
||||||
|
import com.atlassian.jira.bc.license.JiraLicenseService;
|
||||||
|
import com.atlassian.jira.bc.license.JiraLicenseService.ValidationResult;
|
||||||
|
import com.atlassian.jira.config.properties.APKeys;
|
||||||
|
import com.atlassian.jira.config.properties.ApplicationProperties;
|
||||||
|
import com.atlassian.jira.license.JiraLicenseManager;
|
||||||
|
import com.atlassian.jira.license.LicenseDetails;
|
||||||
|
import com.atlassian.jira.util.UrlValidator;
|
||||||
|
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.opensymphony.util.TextUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.atlassian.crowd.embedded.api.CrowdDirectoryService;
|
||||||
|
import com.atlassian.crowd.embedded.api.Directory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JiraApplicationHelper {
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
private final JiraI18nHelper i18nHelper;
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final JiraLicenseManager licenseManager;
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final JiraLicenseService licenseService;
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final CrowdDirectoryService crowdDirectoryService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param applicationProperties injected {@link ApplicationProperties}
|
||||||
|
* @param i18nHelper injected {@link JiraI18nHelper}
|
||||||
|
* @param licenseManager injected {@link JiraLicenseManager}
|
||||||
|
* @param licenseService injected {@link JiraLicenseService}
|
||||||
|
* @param crowdDirectoryService injected {@link CrowdDirectoryService}
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public JiraApplicationHelper(
|
||||||
|
final ApplicationProperties applicationProperties,
|
||||||
|
final JiraI18nHelper i18nHelper,
|
||||||
|
final JiraLicenseManager licenseManager,
|
||||||
|
final JiraLicenseService licenseService,
|
||||||
|
final CrowdDirectoryService crowdDirectoryService) {
|
||||||
|
|
||||||
|
this.applicationProperties = applicationProperties;
|
||||||
|
this.i18nHelper = i18nHelper;
|
||||||
|
this.licenseManager = licenseManager;
|
||||||
|
this.licenseService = licenseService;
|
||||||
|
this.crowdDirectoryService = crowdDirectoryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void syncDir(@Nonnull final Long dirId ) {
|
||||||
|
crowdDirectoryService.synchroniseDirectory(dirId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Directory> getDir() {
|
||||||
|
return crowdDirectoryService.findAllDirectories();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return applicationProperties.getString(APKeys.JIRA_BASEURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBaseUrl(
|
||||||
|
@Nonnull final String baseUrl) {
|
||||||
|
|
||||||
|
if (!UrlValidator.isValid(baseUrl)) {
|
||||||
|
throw new IllegalArgumentException(i18nHelper.getText("admin.errors.you.must.set.a.valid.base.url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationProperties.setString(APKeys.JIRA_BASEURL, baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMode() {
|
||||||
|
return applicationProperties.getString(APKeys.JIRA_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(
|
||||||
|
@Nonnull final String mode) {
|
||||||
|
|
||||||
|
if (!mode.equalsIgnoreCase("public") && !mode.equalsIgnoreCase("private")) {
|
||||||
|
throw new IllegalArgumentException("Invalid mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equalsIgnoreCase("public") && hasExternalUserManagement()) {
|
||||||
|
throw new IllegalArgumentException(i18nHelper.getText("admin.errors.invalid.mode.externalUM.combination"));
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationProperties.setString(APKeys.JIRA_MODE, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return applicationProperties.getString(APKeys.JIRA_TITLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(
|
||||||
|
@Nonnull final String title) {
|
||||||
|
|
||||||
|
if (!TextUtils.stringSet(title)) {
|
||||||
|
throw new IllegalArgumentException(i18nHelper.getText("admin.errors.you.must.set.an.application.title"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.length(title) > 255) {
|
||||||
|
throw new IllegalArgumentException(i18nHelper.getText("admin.errors.invalid.length.of.an.application.title"));
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationProperties.setString(APKeys.JIRA_TITLE, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasExternalUserManagement() {
|
||||||
|
return applicationProperties.getOption(APKeys.JIRA_OPTION_USER_EXTERNALMGT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all licenses.
|
||||||
|
*
|
||||||
|
* @return licenses details
|
||||||
|
*/
|
||||||
|
public Collection<LicenseDetails> getLicenses() {
|
||||||
|
return Lists.newArrayList(licenseManager.getLicenses());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a new license key and clear all licenses before if wanted.
|
||||||
|
*
|
||||||
|
* @param key the license key
|
||||||
|
* @param clear whether to remove all licenses before setting the new license
|
||||||
|
* @return license details
|
||||||
|
*/
|
||||||
|
public LicenseDetails setLicense(
|
||||||
|
final String key,
|
||||||
|
boolean clear) {
|
||||||
|
|
||||||
|
final ValidationResult validationResult = licenseService.validate(i18nHelper.getI18nHelper(), key);
|
||||||
|
|
||||||
|
if (validationResult.getErrorCollection().hasAnyErrors()) {
|
||||||
|
throw new IllegalArgumentException("Specified license was invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String licenseString = validationResult.getLicenseString();
|
||||||
|
|
||||||
|
return clear
|
||||||
|
? licenseManager.clearAndSetLicenseNoEvent(licenseString)
|
||||||
|
: licenseManager.setLicenseNoEvent(licenseString);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package su.tiburon.atlassian.jira;
|
||||||
|
|
||||||
|
import com.atlassian.jira.user.preferences.PreferenceKeys;
|
||||||
|
import com.atlassian.jira.util.I18nHelper;
|
||||||
|
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
|
||||||
|
import com.opensymphony.module.propertyset.PropertySet;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JiraI18nHelper {
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final I18nHelper.BeanFactory i18nBeanFactory;
|
||||||
|
|
||||||
|
private final JiraUserHelper userHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18nBeanFactory injected {@link I18nHelper.BeanFactory}
|
||||||
|
* @param userHelper injected {@link JiraUserHelper}
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public JiraI18nHelper(
|
||||||
|
final I18nHelper.BeanFactory i18nBeanFactory,
|
||||||
|
final JiraUserHelper userHelper) {
|
||||||
|
|
||||||
|
this.i18nBeanFactory = i18nBeanFactory;
|
||||||
|
this.userHelper = userHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText(
|
||||||
|
final String key) {
|
||||||
|
|
||||||
|
return getI18nHelper().getText(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public I18nHelper getI18nHelper() {
|
||||||
|
return i18nBeanFactory.getInstance(getLocale());
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale getLocale() {
|
||||||
|
final PropertySet userProperties = userHelper.getUserProperties();
|
||||||
|
|
||||||
|
if (userProperties != null) {
|
||||||
|
final String locale = userProperties.getString(PreferenceKeys.USER_LOCALE);
|
||||||
|
|
||||||
|
if (locale != null) {
|
||||||
|
return new Locale(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Locale.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package su.tiburon.atlassian.jira;
|
||||||
|
|
||||||
|
import com.atlassian.jira.security.JiraAuthenticationContext;
|
||||||
|
import com.atlassian.jira.user.ApplicationUser;
|
||||||
|
import com.atlassian.jira.user.UserPropertyManager;
|
||||||
|
import com.atlassian.jira.user.preferences.UserPreferencesManager;
|
||||||
|
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
|
||||||
|
import com.opensymphony.module.propertyset.PropertySet;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JiraUserHelper {
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final JiraAuthenticationContext authenticationContext;
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final UserPropertyManager userPropertyManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param authenticationContext injected {@link JiraAuthenticationContext}
|
||||||
|
* @param userPropertyManager injected {@link UserPreferencesManager}
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public JiraUserHelper(
|
||||||
|
final JiraAuthenticationContext authenticationContext,
|
||||||
|
final UserPropertyManager userPropertyManager) {
|
||||||
|
|
||||||
|
this.authenticationContext = authenticationContext;
|
||||||
|
this.userPropertyManager = userPropertyManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get logged in user.
|
||||||
|
*
|
||||||
|
* @return user
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public ApplicationUser getLoggedInUser() {
|
||||||
|
return authenticationContext.getLoggedInUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the property set of the logged in user.
|
||||||
|
*
|
||||||
|
* @return property set
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public PropertySet getUserProperties() {
|
||||||
|
return getUserProperties(getLoggedInUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the property set of the given user.
|
||||||
|
*
|
||||||
|
* @param user the application user
|
||||||
|
* @return property set
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public PropertySet getUserProperties(
|
||||||
|
@Nullable final ApplicationUser user) {
|
||||||
|
|
||||||
|
if (user != null) {
|
||||||
|
return userPropertyManager.getPropertySet(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package su.tiburon.atlassian.jira;
|
||||||
|
|
||||||
|
import com.atlassian.jira.security.GlobalPermissionManager;
|
||||||
|
import com.atlassian.jira.user.ApplicationUser;
|
||||||
|
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import static com.atlassian.jira.permission.GlobalPermissionKey.SYSTEM_ADMIN;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JiraWebAuthenticationHelper {
|
||||||
|
|
||||||
|
@ComponentImport
|
||||||
|
private final GlobalPermissionManager globalPermissionManager;
|
||||||
|
|
||||||
|
private final JiraUserHelper userHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param userHelper the injected {@link JiraUserHelper}
|
||||||
|
* @param globalPermissionManager the injected {@link GlobalPermissionManager}
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public JiraWebAuthenticationHelper(
|
||||||
|
final GlobalPermissionManager globalPermissionManager,
|
||||||
|
final JiraUserHelper userHelper) {
|
||||||
|
|
||||||
|
this.globalPermissionManager = globalPermissionManager;
|
||||||
|
this.userHelper = userHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mustBeSysAdmin() {
|
||||||
|
final ApplicationUser user = userHelper.getLoggedInUser();
|
||||||
|
if (user == null) {
|
||||||
|
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean isSysAdmin = globalPermissionManager.hasPermission(SYSTEM_ADMIN, user);
|
||||||
|
if (!isSysAdmin) {
|
||||||
|
throw new WebApplicationException(Response.Status.FORBIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package su.tiburon.atlassian.jira.bean;
|
||||||
|
|
||||||
|
import com.atlassian.application.api.ApplicationKey;
|
||||||
|
import com.atlassian.jira.license.LicenseDetails;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean for {@link com.atlassian.jira.license.LicenseDetails} results in REST responses.
|
||||||
|
*/
|
||||||
|
@XmlRootElement(name = "license")
|
||||||
|
public class LicenseBean {
|
||||||
|
|
||||||
|
@XmlElement
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
@XmlElement
|
||||||
|
private final Collection<String> applicationKeys;
|
||||||
|
|
||||||
|
private LicenseBean(
|
||||||
|
final String key,
|
||||||
|
final Collection<String> applicationKeys) {
|
||||||
|
|
||||||
|
this.key = key;
|
||||||
|
this.applicationKeys = applicationKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ApplicationKey> getApplicationKeys() {
|
||||||
|
return applicationKeys.stream()
|
||||||
|
.map(ApplicationKey::valueOf)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof LicenseBean) {
|
||||||
|
LicenseBean other = (LicenseBean) obj;
|
||||||
|
|
||||||
|
return Objects.equals(key, other.key)
|
||||||
|
&& Objects.equals(applicationKeys, other.applicationKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(key, applicationKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for creating a bean from {@link LicenseDetails}.
|
||||||
|
*
|
||||||
|
* @param licenseDetail the license details
|
||||||
|
*/
|
||||||
|
public static LicenseBean from(
|
||||||
|
final LicenseDetails licenseDetail) {
|
||||||
|
|
||||||
|
final String key = licenseDetail.getLicenseString();
|
||||||
|
final Collection<String> applicationKeys = licenseDetail.getLicensedApplications().getKeys().stream()
|
||||||
|
.map(ApplicationKey::value)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
return new LicenseBean(key, applicationKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package su.tiburon.atlassian.jira.bean;
|
||||||
|
|
||||||
|
import com.atlassian.jira.license.LicenseDetails;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean for collection of {@link LicenseDetails} results in REST responses.
|
||||||
|
*/
|
||||||
|
@XmlRootElement(name = "licenses")
|
||||||
|
public class LicensesBean {
|
||||||
|
|
||||||
|
@XmlElement
|
||||||
|
private final Collection<LicenseBean> licenses;
|
||||||
|
|
||||||
|
private LicensesBean(
|
||||||
|
final Collection<LicenseBean> licenses) {
|
||||||
|
|
||||||
|
this.licenses = licenses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<LicenseBean> getLicenses() {
|
||||||
|
return licenses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for creating a bean from a collection of {@link LicenseDetails}.
|
||||||
|
*
|
||||||
|
* @param licenseDetails the license details
|
||||||
|
*/
|
||||||
|
public static LicensesBean from(
|
||||||
|
final Collection<LicenseDetails> licenseDetails) {
|
||||||
|
|
||||||
|
final Collection<LicenseBean> licenses = licenseDetails.stream()
|
||||||
|
.map(LicenseBean::from)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
return new LicensesBean(licenses);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package su.tiburon.atlassian.jira.bean;
|
||||||
|
|
||||||
|
import su.tiburon.atlassian.jira.JiraApplicationHelper;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean for setting results in REST responses.
|
||||||
|
*/
|
||||||
|
@XmlRootElement(name = "settings")
|
||||||
|
public class SettingsBean {
|
||||||
|
|
||||||
|
@XmlElement
|
||||||
|
private final String baseurl;
|
||||||
|
|
||||||
|
@XmlElement
|
||||||
|
private final String mode;
|
||||||
|
|
||||||
|
@XmlElement
|
||||||
|
private final String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default constructor is needed for JSON request deserialization.
|
||||||
|
*/
|
||||||
|
public SettingsBean() {
|
||||||
|
this.baseurl = null;
|
||||||
|
this.mode = null;
|
||||||
|
this.title = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsBean(
|
||||||
|
final String baseUrl,
|
||||||
|
final String mode,
|
||||||
|
final String title) {
|
||||||
|
|
||||||
|
this.baseurl = baseUrl;
|
||||||
|
this.mode = mode;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsBean(
|
||||||
|
final JiraApplicationHelper applicationHelper) {
|
||||||
|
|
||||||
|
this.baseurl = applicationHelper.getBaseUrl();
|
||||||
|
this.mode = applicationHelper.getMode();
|
||||||
|
this.title = applicationHelper.getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return baseurl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package su.tiburon.atlassian.jira.rest;
|
||||||
|
|
||||||
|
import com.atlassian.jira.rest.api.util.ErrorCollection;
|
||||||
|
import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
|
||||||
|
import su.tiburon.atlassian.jira.JiraApplicationHelper;
|
||||||
|
import su.tiburon.atlassian.jira.JiraWebAuthenticationHelper;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.atlassian.crowd.embedded.api.Directory;
|
||||||
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings resource to get the licenses.
|
||||||
|
*/
|
||||||
|
@Path("/directory")
|
||||||
|
@AnonymousAllowed
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Component
|
||||||
|
public class DirectoriesResource {
|
||||||
|
|
||||||
|
private final JiraApplicationHelper applicationHelper;
|
||||||
|
|
||||||
|
private final JiraWebAuthenticationHelper webAuthenticationHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param applicationHelper the injected {@link JiraApplicationHelper}
|
||||||
|
* @param webAuthenticationHelper the injected {@link JiraWebAuthenticationHelper}
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public DirectoriesResource(
|
||||||
|
final JiraApplicationHelper applicationHelper,
|
||||||
|
final JiraWebAuthenticationHelper webAuthenticationHelper) {
|
||||||
|
|
||||||
|
this.applicationHelper = applicationHelper;
|
||||||
|
this.webAuthenticationHelper = webAuthenticationHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response syncDir(@QueryParam("id") Long dirId) throws WebApplicationException {
|
||||||
|
|
||||||
|
webAuthenticationHelper.mustBeSysAdmin();
|
||||||
|
|
||||||
|
final ErrorCollection errorCollection = ErrorCollection.of();
|
||||||
|
|
||||||
|
if (dirId != null) {
|
||||||
|
try {
|
||||||
|
applicationHelper.syncDir(dirId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorCollection.addErrorMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new WebApplicationException(Response.Status.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
if (errorCollection.hasAnyErrors()) {
|
||||||
|
return Response.ok(errorCollection).build();
|
||||||
|
} else {
|
||||||
|
return Response.ok(null).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getDir() {
|
||||||
|
webAuthenticationHelper.mustBeSysAdmin();
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
final List<Directory> directories = applicationHelper.getDir();
|
||||||
|
String jsn = "";
|
||||||
|
try {
|
||||||
|
jsn = mapper.writeValueAsString(directories);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return Response.ok(jsn).build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package su.tiburon.atlassian.jira.rest;
|
||||||
|
|
||||||
|
import com.atlassian.jira.license.LicenseDetails;
|
||||||
|
import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
|
||||||
|
import su.tiburon.atlassian.jira.JiraApplicationHelper;
|
||||||
|
import su.tiburon.atlassian.jira.JiraWebAuthenticationHelper;
|
||||||
|
import su.tiburon.atlassian.jira.bean.LicenseBean;
|
||||||
|
import su.tiburon.atlassian.jira.bean.LicensesBean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Licenses resource to get the licenses.
|
||||||
|
*/
|
||||||
|
@Path("/licenses")
|
||||||
|
@AnonymousAllowed
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Component
|
||||||
|
public class LicensesResource {
|
||||||
|
|
||||||
|
private final JiraApplicationHelper applicationHelper;
|
||||||
|
|
||||||
|
private final JiraWebAuthenticationHelper webAuthenticationHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param applicationHelper the injected {@link JiraApplicationHelper}
|
||||||
|
* @param webAuthenticationHelper the injected {@link JiraWebAuthenticationHelper}
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public LicensesResource(
|
||||||
|
final JiraApplicationHelper applicationHelper,
|
||||||
|
final JiraWebAuthenticationHelper webAuthenticationHelper) {
|
||||||
|
|
||||||
|
this.applicationHelper = applicationHelper;
|
||||||
|
this.webAuthenticationHelper = webAuthenticationHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getLicenses() {
|
||||||
|
webAuthenticationHelper.mustBeSysAdmin();
|
||||||
|
|
||||||
|
final Collection<LicenseDetails> licenseDetails = applicationHelper.getLicenses();
|
||||||
|
return Response.ok(LicensesBean.from(licenseDetails)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Consumes(MediaType.TEXT_PLAIN)
|
||||||
|
public Response setLicense(
|
||||||
|
@QueryParam("clear") @DefaultValue("false") boolean clear,
|
||||||
|
final String licenseKey) throws WebApplicationException {
|
||||||
|
|
||||||
|
webAuthenticationHelper.mustBeSysAdmin();
|
||||||
|
|
||||||
|
if (licenseKey == null) {
|
||||||
|
throw new WebApplicationException(Response.Status.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
final LicenseDetails licenseDetail = applicationHelper.setLicense(licenseKey, clear);
|
||||||
|
return Response.ok(LicenseBean.from(licenseDetail)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package su.tiburon.atlassian.jira.rest;
|
||||||
|
|
||||||
|
import com.atlassian.jira.rest.api.util.ErrorCollection;
|
||||||
|
import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
|
||||||
|
import su.tiburon.atlassian.jira.JiraApplicationHelper;
|
||||||
|
import su.tiburon.atlassian.jira.JiraWebAuthenticationHelper;
|
||||||
|
import su.tiburon.atlassian.jira.bean.SettingsBean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings resource to get the licenses.
|
||||||
|
*/
|
||||||
|
@Path("/settings")
|
||||||
|
@AnonymousAllowed
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Component
|
||||||
|
public class SettingsResource {
|
||||||
|
|
||||||
|
private final JiraApplicationHelper applicationHelper;
|
||||||
|
|
||||||
|
private final JiraWebAuthenticationHelper webAuthenticationHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param applicationHelper the injected {@link JiraApplicationHelper}
|
||||||
|
* @param webAuthenticationHelper the injected {@link JiraWebAuthenticationHelper}
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public SettingsResource(
|
||||||
|
final JiraApplicationHelper applicationHelper,
|
||||||
|
final JiraWebAuthenticationHelper webAuthenticationHelper) {
|
||||||
|
|
||||||
|
this.applicationHelper = applicationHelper;
|
||||||
|
this.webAuthenticationHelper = webAuthenticationHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getSettings() {
|
||||||
|
webAuthenticationHelper.mustBeSysAdmin();
|
||||||
|
|
||||||
|
final SettingsBean settingsBean = new SettingsBean(applicationHelper);
|
||||||
|
return Response.ok(settingsBean).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response setSettings(
|
||||||
|
final SettingsBean settingsBean) {
|
||||||
|
|
||||||
|
webAuthenticationHelper.mustBeSysAdmin();
|
||||||
|
|
||||||
|
final ErrorCollection errorCollection = ErrorCollection.of();
|
||||||
|
|
||||||
|
if (settingsBean.getBaseUrl() != null) {
|
||||||
|
try {
|
||||||
|
applicationHelper.setBaseUrl(settingsBean.getBaseUrl());
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorCollection.addErrorMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingsBean.getMode() != null) {
|
||||||
|
try {
|
||||||
|
applicationHelper.setMode(settingsBean.getMode());
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorCollection.addErrorMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingsBean.getTitle() != null) {
|
||||||
|
try {
|
||||||
|
applicationHelper.setTitle(settingsBean.getTitle());
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorCollection.addErrorMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.ok(errorCollection).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:atlassian-scanner="http://www.atlassian.com/schema/atlassian-scanner/2"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
|
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||||
|
http://www.atlassian.com/schema/atlassian-scanner/2
|
||||||
|
http://www.atlassian.com/schema/atlassian-scanner/2/atlassian-scanner.xsd">
|
||||||
|
<atlassian-scanner:scan-indexes/>
|
||||||
|
</beans>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
|
||||||
|
<plugin-info>
|
||||||
|
<description>${project.description}</description>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<vendor name="${project.organization.name}" url="${project.organization.url}" />
|
||||||
|
<param name="plugin-icon">images/logo_octo_375_293.png</param>
|
||||||
|
<param name="plugin-logo">images/logo_octo_375_293.png</param>
|
||||||
|
</plugin-info>
|
||||||
|
|
||||||
|
<resource type="i18n" name="i18n" location="rest-extender"/>
|
||||||
|
|
||||||
|
<web-resource key="rest-extender-web-resource" name="JIRA REST Extender Web Resource">
|
||||||
|
<dependency>com.atlassian.auiplugin:ajs</dependency>
|
||||||
|
<dependency>com.atlassian.auiplugin:aui-experimental-expander</dependency>
|
||||||
|
<resource type="download" name="images/" location="/images"/>
|
||||||
|
<context>atl.general</context>
|
||||||
|
</web-resource>
|
||||||
|
|
||||||
|
<rest key="rest-extender" name="JIRA REST Extender" path="/extender" version="1"/>
|
||||||
|
|
||||||
|
</atlassian-plugin>
|
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
Loading…
Reference in New Issue