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